Добавить строку префикса в начало каждой строки

У меня есть файл, как показано ниже:

line1
line2
line3

И я хочу получить:

prefixline1
prefixline2
prefixline3

Я мог бы написать сценарий Ruby, но лучше, если мне это не нужно.

prefix будет содержать /. Это путь, например /opt/workdir/.


person pierrotlefou    schedule 20.01.2010    source источник


Ответы (17)


# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file

# If you want to create a new file
sed -e 's/^/prefix/' file > file.new

Если prefix содержит /, вы можете использовать любой другой символ, не входящий в prefix, или экранировать /, так что команда sed станет

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'
person Alok Singhal    schedule 20.01.2010
comment
если префикс содержит /, то его проще использовать awk. - person Vijay; 20.01.2010
comment
@benjamin, я уже проголосовал за ваш ответ, однако я предпочитаю sed для таких легких задач, как эта. Если префикс известен, очень легко выбрать символ не из префикса. - person Alok Singhal; 20.01.2010
comment
Не забывайте, что вы также можете использовать sed в конвейере, например foo | sed -e 's/^/x /' | bar. - person zigg; 13.03.2014
comment
@AlokSinghal: Как применить свой ответ ко всем строкам в файле, кроме first line (header)? - person Dataman; 21.10.2014
comment
@AlokSinghal: Кажется, я нашел свой ответ: sed -e '1!s/^/prefix/' file. - person Dataman; 21.10.2014
comment
@ Датаман круто. Другой способ - sed -e '2,$s/^/prefix/'. - person Alok Singhal; 21.10.2014
comment
Также можно упомянуть, что если у вас есть префикс в переменной, вы не можете использовать одинарные кавычки. sed "s%^%$PREFIX%" file (с использованием двойных кавычек для включения интерполяции переменных; и % в качестве альтернативного разделителя при условии, что $PREFIX может содержать косую черту, но не будет содержать знаков процента). - person tripleee; 25.06.2015
comment
@BinChen экранирует /, например \/ (в строках с одинарными кавычками) или \\/ (в строках с двойными кавычками) - person ; 28.03.2017
comment
Используйте sed -e 's/$/postfix/' file, если хотите добавить строку в конец каждой строки. - person Brian; 29.06.2017
comment
Если вы обрабатываете большие входные данные, подумайте о том, чтобы попробовать Perl. perl -ne $| = 1;print "prefix$_". В моем тесте это было примерно в 80 раз быстрее, чем sed. Подробнее см. Это сообщение в блоге rc3.org/2014 / 08/28 / удивительно-perl-outperforms-sed-and-awk на twitter.com/rafeco - person derflocki; 15.02.2018
comment
для добавления табуляции после слова sed -i -e 's / ^ / prefix \ t /' testfile.txt - person Mian Asbat Ahmad; 06.07.2018
comment
Вам не нужно использовать / в качестве разделителя с sed, вы можете использовать что-то вроде s.^./., чтобы добавить косую черту в начале каждой строки. В качестве разделителя можно использовать любой символ. - person ; 27.08.2018
comment
@Dev - да, я упомянул об этом в своем ответе. - person Alok Singhal; 28.08.2018
comment
Нет, это не так. Вы упомянули, что можете сбежать /. - person ; 28.08.2018
comment
Я писал: Если prefix содержит /, вы можете использовать любой другой символ, не входящий в prefix, а затем пример без /. - person Alok Singhal; 28.08.2018
comment
Почему вы используете параметр -e и не могли бы вы также объяснить, почему вы не ставите g в конце? - person mf94; 11.09.2018
comment
Я использую -e по привычке, потому что иногда мне нужно несколько команд в одном sed вызове. В этом случае g в конце на самом деле ничего не сделает, поскольку шаблон может соответствовать только один раз в строке. - person Alok Singhal; 11.09.2018
comment
В приведенном примере с sed пропущены строки, на которых есть только новая строка (пустые строки). Awk, как указано в другом месте на этой странице, обрабатывает все строки. - person unifex; 06.10.2018
comment
@unifex Странно. Я просто попробовал это с тестовым файлом, и он не пропускает пустые строки. - person Alok Singhal; 07.10.2018

awk '$0="prefix"$0' file > new_file

С Perl (вместо замены):

perl -pi 's/^/prefix/' file
person Vijay    schedule 20.01.2010
comment
С конвейером / потоком или переменной: prtinf "$VARIABLE\n" | awk '$0="prefix"$0' - person ThorSummoner; 25.02.2015
comment
В случае большого файла (12 ГБ) awk сообщает awk: out of memory in readrec 1 source line number 1, но решение с sed завершается успешно. - person jrm; 06.07.2017

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

ex -sc '%s/^/prefix/|x' file
  1. % выбрать все строки

  2. s заменить

  3. x сохранить и закрыть

person Steven Penny    schedule 30.09.2012
comment
Я просто открываю файл в vim и набираю :%s/^/prefix/, так как эта стратегия оказывается полезной во многих ситуациях. - person Frank Bryce; 02.02.2017

Если ваш префикс немного сложен, просто поместите его в переменную:

prefix=path/to/file/

Затем вы передаете эту переменную и позволяете awk разбираться с ней:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt
person Melka    schedule 17.02.2015

Если у вас есть Perl:

perl -pe 's/^/PREFIX/' input.file
person Majid Azimi    schedule 11.12.2013

Вот удобочитаемое одинарное решение с использованием ts команда из moreutils

$ cat file | ts prefix | tr -d ' '

И как это выведено пошагово:

# Step 0. create the file

$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line

$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle

$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3
person navigaid    schedule 19.04.2019
comment
'ts' не установлен по умолчанию во многих дистрибутивах Linux. Кроме того, голосование против, потому что завершающий tr -d '' в этом ответе удалит все пробелы из строк, а не только пространство, которое было добавлено 'ts' - person Tim Bird; 13.05.2020

Используя оболочку:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file
person ghostdog74    schedule 20.01.2010

Использование & (вся часть ввода, соответствующая шаблону »):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

ИЛИ используя обратные ссылки:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt
person Ark25    schedule 05.04.2020

Хотя я не думаю, что у Pierr была эта проблема, мне нужно было решение, которое не задерживало бы вывод из живого «хвоста» файла, так как я хотел отслеживать несколько журналов предупреждений одновременно, добавляя к каждой строке имя соответствующего журнала. .

К сожалению, sed, cut и т. Д. Вводят слишком много буферизации и не позволяют мне видеть самые свежие строки. Предложение Стивена Пенни использовать параметр -s для nl было интригующим, и тестирование показало, что оно не привело к нежелательной буферизации, которая меня беспокоила.

Однако при использовании nl возникла пара проблем, связанных с желанием вырезать ненужные номера строк (даже если вас не волнует его эстетика, могут быть случаи, когда использование дополнительных столбцов было бы нежелательно) . Во-первых, использование слова «вырезать» для вырезания чисел вновь вызывает проблему буферизации, так что это разрушает решение. Во-вторых, использование «-w1» не помогает, поскольку это НЕ ограничивает номер строки одним столбцом - он просто становится шире по мере того, как требуется больше цифр.

Это некрасиво, если вы хотите запечатлеть это в другом месте, но поскольку это именно то, что мне не нужно было делать (все уже записывалось в файлы журнала, я просто хотел посмотреть несколько сразу в режиме реального времени), лучший способ потерять номера строк и иметь только мой префикс состоял в том, чтобы начать строку -s с возврата каретки (CR или ^ M или Ctrl-M). Так например:

#!/bin/ksh

# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.

PGRP=$$

for LOGFILE in widget framas dweezil
do
(
    tail -f $LOGFILE 2>&1 |
    nl -s"^M${LOGFILE}>  "
) &
sleep 1
done

read KILLEM

kill -- -${PGRP}
person ScriptGuy    schedule 07.03.2014
comment
используйте параметр -u для sed, чтобы избежать буферизации. - person Bryan Larsen; 08.03.2014
comment
Буферизацию можно отключить с помощью unbuffer / stdbuf, см. unix.stackexchange.com/q/25372/6205 - person myroslav; 04.06.2015

Используя ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

Это заменяет для каждой строки (,) начало строки (^) на prefix. wq сохраняется и выходит.

Если строка замены содержит косую черту, мы можем вместо этого использовать другой разделитель для s:

ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE

Я процитировал разделитель here-doc EOE ("конец редактора"), чтобы предотвратить расширение параметра. В этом примере он также будет работать без кавычек, но это хорошая практика, чтобы избежать сюрпризов, если у вас когда-либо будет $ в вашем сценарии ed.

person Benjamin W.    schedule 28.06.2018

Вот завершенный пример с использованием подхода sed из этого ответа:

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

prefix_lines

function show_help()
{
  IT=$(CAT <<EOF
    Usage: PREFIX {FILE}

    e.g.

    cat /path/to/file | prefix_lines "WOW: "

      WOW: some text
      WOW: another line
      WOW: more text
  )
  echo "$IT"
  exit
}

# Require a prefix
if [ -z "$1" ]
then
  show_help
fi

# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
  # If no stdin exists
  if [ -t 0 ]; then
    show_help
  fi
  FILE=/dev/stdin
fi

# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE
person Brad Parks    schedule 16.03.2016
comment
Это не сработает, если PREFIX содержит какие-либо символы, специально предназначенные для sed, например косую черту. - person josch; 03.01.2017
comment
Хороший момент ... Если вы обнаружите, что часто используете косую черту, вы можете использовать другой разделитель с частью sed, , как подробно описано здесь, что позволит вам использовать его в поиске. Другие специальные символы sed могут быть вставлены с помощью косой черты, например prefix_lines \* - person Brad Parks; 03.01.2017

  1. Вы также можете добиться этого, используя технику обратной ссылки

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Вы также можете использовать с awk вот так

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    
person k_vishwanath    schedule 11.04.2020

Использование Pythonize (pz):

pz '"preix"+s' <filename
person Hans Ginzel    schedule 22.03.2021

Для людей, использующих системы BSD / OSX, есть утилита под названием lam, сокращенно от слова "ламинат". lam -s prefix file будет делать то, что вы хотите. Я использую его в конвейерах, например:

find -type f -exec lam -s "{}: " "{}" \; | fzf

... который найдет все файлы, выполняет lam для каждого из них, присваивая каждому файлу префикс его собственного имени файла. (И качаем вывод в fzf для поиска.)

person Ray    schedule 19.04.2019
comment
Вы правы, похоже, это только команда BSD. POSIX заменил его на paste, но paste не имеет функции добавления полной разделительной строки. Я обновлю свой ответ. - person Ray; 15.12.2019

Если вам нужно добавить текст в начало каждой строки, содержащей определенную строку, попробуйте выполнить следующее. В следующем примере я добавляю # в начале каждой строки, в которой есть слово рок.

sed -i -e 's/^.*rock.*/#&/' file_name
person mandroid    schedule 10.12.2020

Простое решение с использованием цикла for в командной строке с помощью bash:

for i in $(cat yourfile.txt); do echo "prefix$i"; done

Сохраните вывод в файл:

for i in $(cat yourfile.txt); do echo "prefix$i"; done > yourfilewithprefixes.txt
person Michael    schedule 18.04.2021

person    schedule
comment
Пожалуйста, добавьте пояснение к своему ответу, чтобы другие могли извлечь из него уроки. - person Nico Haase; 10.11.2020
comment
Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением обычно более полезны и качественнее, и с большей вероятностью соберут положительные голоса. - person Yagiz Degirmenci; 10.11.2020
comment
Если бы вы искали ответ в базе знаний, пытаясь решить проблему, как вы думаете, будет ли этот ответ полезным? Не так много. - person Trenton McKinney; 11.11.2020