Harald Dunkel wrote on Mon, Aug 01, 2022 at 09:08:40AM +0200: > a colleague pointed me to a changed behavior of bash 5.1.4 in Debian 11. > Would you mind to take a look at this code? > > ---- > #! /bin/bash > # set -x > > insert() > { > local data="$1" > local lineNumber="$2" > > head -n "$lineNumber"
The problem is that stdin is eaten up by this head command. What changed is that bash used to store stdin input in a temporary file, so head could seek back to the actual position in the stream after the first three lines but that no longer works: 1007746 read(0, "this is line one\nthis is line two\nthis is line three\nthis is line four\nthis is line five\nthis is line six\nthis is line seven\n", 8192) = 125 1007746 lseek(0, -72, SEEK_CUR) = -1 ESPIPE (Illegal seek) In bash 5.0 0 here was a temporary file in /tmp, and that lseek worked, but you cannot rely on that in general -- splitting stdin is difficult business... You'll get the same behaviour back if you go through a temporary file again e.g. (don't actually do that!!) ---- echo "$text" > /tmp/temp output="$( insert "Hello" 3 < /tmp/temp )" rm /tmp/temp ---- Now as for how to actually do this, tough question. If your example is representative of your real text you can just use awk or any other single command: ---- insert() { local data="$1" local lineNumber="$2" awk -v lineno=$lineNumber -v data="$data" \ '{ print } NR == lineno { print "blabla", data }' } ---- -- Dominique