Какой самый простой способ добавить строку в начале каждой строки файла из командной строки?

8

Я ищу способ добавить некоторую строку в начало каждой строки (та же строка для каждой строки). Не что-то настраиваемое, а скорее то, что будет легко запомнить и доступно на любой POSIX-совместимой платформе (и каждой оболочке).

синтагма
источник

Ответы:

8

Вы можете использовать sed:

sed -i 's/^/your_string /' your_file

Благодаря комментариям Стефана и Марко, обратите внимание, что -iопция не POSIX. POSIX способ сделать это будет

sed 's/^/your_string /' your_file > tmp_copy && mv tmp_copy your_file

или perl:

perl -pi -e 's/^/your_string /' your_file

объяснение

Обе команды выполняют подстановку регулярных выражений, заменяя начало строки ( ^) желаемой строкой. -iПереключатель в обеих командах убеждается файл редактируется на месте (т.е. изменения отражаются в файле вместо печати на стандартный вывод).

sedдолжен быть доступен в любой POSIX-совместимой ОС и perlдолжен быть доступен в большинстве современных Unix-систем, за исключением, возможно, тех, которые прошли через его удаление.

Джозеф Р.
источник
1
Небольшое исправление: -iпереключатель не редактирует файл на месте. Он создает новый файл и перезаписывает исходный после того, как это сделано (доказательство: индекс изменяется). Существует не так много инструментов, которые фактически выполняют редактирование на месте, что является опасной операцией. Кроме того, поскольку вы упоминаете POSIX, -iпереключатель не является обязательным для POSIX-совместимого sed, это особенность некоторых конкретных реализаций.
Марко
2
sed -iэто не POSIX. Это GNU. У FreeBSD sedесть похожая опция, но она вам нужна sed -i ''.
Стефан Шазелас
@ Марко Я знаю, что -iсоздает временную копию (поэтому я сказал, что изменения отражены в исходном файле); Я имел в виду, что вы получаете ту же семантику, что и замена на месте. Пожалуйста, убедитесь, что обновленный ответ соответствует POSIX.
Джозеф Р.
Строго говоря, изменения отражаются в новом файле с тем же именем, что и оригинал.
Кит Томпсон
1
Я часто использую $$(идентификатор процесса текущей оболочки) как часть временного имени файла; он избегает попыток каждый раз command filename > filename.$$ && mv filename.$$ filename
придумывать
14
:|paste -d'foo ' - - - - input > output

(шучу, хотя вы, вероятно, найдете самое быстрое из всех решений, опубликованных здесь: -b).

Канонический способ это:

sed 's/^/foo /' < input > output

Однако его нелегко адаптировать к произвольным строкам. Например,

sed "s/^/$var /"

Работает только если $varне содержит, &, \, /ни символы новой строки.

В связи с этим

export var
awk '{print ENVIRON["var"], $0}'

или

perl -pe '$_="$ENV{var} $_"'

будет работать лучше.

Стефан Шазелас
источник
это что-то интересное ...: P
Рахул Патил
4

Я представляю решение, используя awkпредварительную строку «foo».

awk '{ print "foo", $0; }' input > output

awkкроссплатформенный и доступен в любой системе POSIX. Это не делает редактирование на месте. Если вы хотите отредактировать файл без создания второго, вам придется использовать временный файл. Смотрите sedответ Джозефа , он показывает синтаксис. Другой способ - использовать следующий синтаксис, который в основном создает временный файл с тем же именем, что и исходный файл.

{ rm file; awk '{ print "foo", $0 }' > file; } < file
Marco
источник
reducto# wc -l foo`914 foo` reducto# { rm foo ; awk '{ print "prepend" , $0 }' > foo } < foo >Это не похоже на работу. Я пытался, потому что перенаправление на оригинал заставило меня нервничать, но оно даже не началось.
Куртм
1
Этот пример будет работать, если он использует круглые скобки, а не фигурные скобки.
Куртм
4

Вы можете избежать проблем редактирования на месте с помощью потоковых инструментов, используя инструмент, который обычно выполняет редактирование на месте - редактор!

ex sample.txt -c "%s/^/foo /" -c wq

Дополнительным преимуществом является то, что команды просты и очевидны для всех, кто разбирается в одном истинном редакторе.

Майк ДеАнджело
источник
2

Вы можете использовать perlдля этого:

$ perl -pi -e 's/^/mystring /' afile.txt

пример

Создать образец файла.

$ seq 5 > afile.txt

$ cat afile.txt
1
2
3
4
5

Запустите приведенную выше команду:

$ perl -pi -e 's/^/mystring /' afile.txt

$ cat afile.txt
mystring 1
mystring 2
mystring 3
mystring 4
mystring 5
SLM
источник
Perl кажется универсальным в наше время, но долгое время это не было. И я держу пари , что есть несколько вариантов UNIX редки, что там упорно отказывается иметь Perl как часть базы. Что-то, о чем нужно знать.
Куртм
@kurtm смотрите обсуждение здесь . По-видимому, в AIX по умолчанию нет Perl, как и встроенных систем.
Terdon
2
@DavidSainty - это достаточно универсально. Q был помечен как Bash, поэтому мне очень трудно представить систему, в которой есть Bash, но нет Perl. Во всяком случае, вот один из 5 ответов, несколько других показывают, как использовать sed, я показал, как использовать Perl .... не ища священной войны по этому вопросу.
SLM
1
@DavidSainty Видимо только OpenBSD. Я предполагаю, что сделал предположение, так как Открытые люди, как правило, консервативны в отношении того, что они допускают в базе. OpenBSD определенно имеет его в базе.
Куртм
1
@slm: « Мне очень трудно представить систему с Bash, но без Perl ». У меня на столе несколько таких систем. (Это, оказывается, встраиваемые системы.)
Кит Томпсон
1

Просто используя Bash

 while IFS= read -r line; do echo "foo" "${line}" ; done  < input > Output

Использование Python

python -c "import sys; print 'foo '.join([ l for l in sys.stdin.readlines() ])" < input > Output

Если вы хотите редактировать на месте

import fileinput
import sys

for line in fileinput.input(['inputfile'], inplace=True):
    sys.stdout.write('foo {l}'.format(l=line))

Ссылка ссылка

Рахул Патил
источник
Почему он работает быстрее, чем awk?
Рахул Патил
1
Это будет работать быстрее, чем awkс очень маленькими файлами. Поведение варьируется в зависимости от реализации эха, и оно удаляет начальные и конечные пробелы и специально обрабатывает обратные слэши.
Стефан Шазелас
@ StephaneChazelas Да. Вы на 100% верны, только что проверили ... paste.ubuntu.com/6210934
Рахул Патил
prefix () { while IFS= read -r REPLY; do printf "%s%s\n" "$1" "$REPLY"; done; }должно быть более правильным.
Мэтт
1
Почему то {}? Я думаю, что @Matt предлагал вам превратить его в именованную функцию, в чем смысл {}без имени функции?
Terdon
-1

Или вы можете сделать следующее:

vi filename.txt

Esc(чтобы убедиться, что вы находитесь в NORMALрежиме), а затем введите следующую команду:

:1,$ s/^/mystring
Dino
источник
Обратите внимание, что, поскольку пользователь спрашивает о каждой строке файла, вы можете 1,$ просто заменить на %. Это делает команду :%s/^/string/.
HalosGhost