Додайте рядок префікса до початку кожного рядка


334

У мене є файл, як показано нижче:

line1
line2
line3

І я хочу отримати:

prefixline1
prefixline2
prefixline3

Я міг би написати сценарій Ruby, але краще, якщо мені цього не потрібно.

prefixбуде містити /. /opt/workdir/Наприклад, це шлях .

Відповіді:


526
# 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/'

1
@benjamin, я вже схвалив вашу відповідь, проте я віддаю перевагу sedлегким завданням, як-от цей. Якщо "префікс" відомий, вибрати символ не з "префікса" дуже просто.
Алок Сінгал

1
Не забувайте, що ви також можете використовувати sedв трубопроводі, наприклад foo | sed -e 's/^/x /' | bar.
зигг

1
@Dataman круто. Інший спосіб був би sed -e '2,$s/^/prefix/'.
Алок Сінгал

1
@BinChen уникнути /подібного \/(у рядках з одним цитуванням) або \\/(у рядках з подвійним котируванням)

8
Використовуйте, sed -e 's/$/postfix/' fileякщо ви хочете додати рядок до кінця кожного рядка.
Брайан

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

З Perl (заміною місця):

perl -pi 's/^/prefix/' file

8
З трубою / потоком або змінною:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner

2
З великим файлом (12 G), awkзвіти awk: out of memory in readrec 1 source line number 1, але рішення з sedзавершено успішно.
jrm

33

Ви можете використовувати Vim в режимі Ex:

ex -sc '%s/^/prefix/|x' file
  1. % виберіть усі рядки

  2. s замінити

  3. x зберегти і закрити


1
Для мене я просто відкриваю файл vim та type :%s/^/prefix/, оскільки ця стратегія виявляється корисною у багатьох ситуаціях
Френк Брайс

23

Якщо ваш префікс трохи складний, просто поставте його в змінну:

prefix=path/to/file/

Потім ви передаєте цю змінну і даєте awk розібратися з нею:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt


6

Використання оболонки:

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

5

Ось високопрочитане рішення з однолінійкою за допомогою 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

"ts" не встановлено за замовчуванням у багатьох дистрибутивах Linux. Крім того, зволікаючи через те, що трелінг "tr -d" "у цій відповіді видалить усі рядки з рядків, а не лише пробіл, який додав" ts "
Тім Берд

3

Хоча я не думаю, що у pierr виникло таке занепокоєння, мені було потрібне рішення, яке не затримуватиме виведення з прямого "хвоста" файлу, оскільки я хотів контролювати кілька журналів попередження одночасно, префіксуючи кожен рядок із назвою відповідного журналу .

На жаль, sed, cut, etc. ввели занадто багато буферизації і не давали мені бачити найбільш актуальні лінії. Пропозиція Стівена Пенні використати -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}

1
використовуйте -uопцію sed, щоб уникнути буферизації.
Брайан Ларсен

2
Буферизацію можна вимкнути за допомогою програми unbuffer / stdbuf, див. Unix.stackexchange.com/q/25372/6205
myroslav

2

Використовуючи ed:

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

Це замінює для кожного рядка ( ,) початок рядка ( ^) на prefix. wqекономить і виходить.

Якщо рядок заміщення містить косу рису, ми можемо використовувати інший роздільник для s:

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

Я цитував роздільник тут-doc EOE("кінець редакції") для запобігання розширення параметрів. У цьому прикладі це може працювати і без котирування, але це хороша практика запобігання сюрпризів, якщо у вас коли-небудь є $сценарій редагування.


2

Використовуючи & (вся частина вводу, яка була узгоджена за шаблоном "):

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

АБО за допомогою зворотних посилань:

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

2
  1. Ви також можете досягти цього, використовуючи техніку зворотного відношення

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Ви також можете використовувати з awk, як це

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

1

Ось зведений приклад використання 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

2
Це не спрацює, якщо PREFIXмістить будь-які символи, спеціальні для sed, як коса риса.
Джош

Добрий момент ... Якщо ви знайдете, що ви використовуєте косу рису, ви можете використовувати інший роздільник з частиною sed, як це детально описано тут , що дозволить вам використовувати його в пошуку. Інші спеціальні сидіння можуть бути введені, рятуючись косою рисою, наприкладprefix_lines \*
Brad Parks

0

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

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

... який знайде всі файли, exec lam на кожному з них, надаючи кожному файлу префікс власного імені файлу. (І перекачуйте вихід на fzf для пошуку.)


Ви маєте рацію, здається, це лише команда BSD. POSIX замінив його на пасту, але в пасту немає функції додавати повний розділовий рядок. Я оновлю свою відповідь.
Рей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.