Более общий ответ заключается в том, что bash и некоторые другие оболочки обычно помещают все элементы конвейера в отдельные процессы. Это разумно, когда командная строка имеет вид
program1 | program2 | program3
поскольку программы обычно выполняются в отдельных процессах.
(если только вы не говорите exec program
).
Но это может стать неожиданностью для
command1 | command2 | command3
команд, где некоторые или все команды являются встроенными командами. Тривиальные примеры включают:
$ a=0
$ echo | a=1
$ echo "$a"
0
$ cd /
$ echo | cd /tmp
$ pwd
/
Чуть более реалистичный пример -
$ t=0
$ ps | while read pid rest_of_line
> do
> : $((t+=pid))
> done
$ echo "$t"
0
где весь цикл while
... do
... done
помещен в подпроцесс,
и поэтому его изменения в t
не видны основной оболочке после завершения цикла.
И это именно то, что вы делаете - передаете данные в цикл while
,
заставляя цикл выполняться как под-оболочка,
а затем пытаетесь вернуться из подцикла.
Asumiendo un archivo POSIX, echo "$(head -c-1 data1)","$(wc -l <data1)"
generará lo que desea. head
elimina la nueva línea final.
Use sed para agregar el número a la última línea:
STRING=`echo "$(wc -l < data1 | bc)"` && sed -i '$s/^\(.*\)$/\1,'"$STRING"'/' data1
$ cat data1
test1,test2,test3,1
La primera parte guarda el número de líneas en la variable STRING
y el sed toma la última línea y agrega la variable ,
y el contenido de $STRING
al final de la línea.
Команда paste
используется для добавления столбцов:
$ wc -l <data1 | paste -d, file -
test1,test2,test3, 1
Это буквально то, что вы просили; вывод wc
добавляется в конец строки файла. Вывод wc
имеет пробелы в начале строки, поэтому вы получаете интервал, который вы получаете здесь.
Чтобы удалить этот пробел:
$ wc -l <data1 | sed 's/^ *//' | paste -d, file -
test1,test2,test3,1
Здесь команда paste
используется с -d,
, что заставляет вставлять запятую между старым и новым столбцами. -
сигнализирует о том, что новые столбцы следует считывать из стандартного ввода, а не из файла. Стандартный ввод исходит от wc -l
, который подсчитывает количество строк в файле.
Вариант с sed
просто берет вывод wc
и удаляет все символы пробела в начале строки.
Использование bash
замены процесса:
paste -d, file <( wc -l <data1 | sed 's/^ *//' )
Здесь подстановка процесса <(... )
занимает место -
.