在每行开头添加前缀字符串


334

我有一个文件如下:

line1
line2
line3

我想得到:

prefixline1
prefixline2
prefixline3

我可以编写一个Ruby脚本,但是如果不需要的话更好。

prefix将包含//opt/workdir/例如,这是一条路径。

Answers:


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执行此类轻量级任务。如果知道“前缀”,则很容易从“前缀”中选择一个字符。
Alok Singhal 2010年

1
别忘了,您也可以sed在管道中使用,例如foo | sed -e 's/^/x /' | bar
Zigg 2014年

1
@Dataman很棒。另一种方法是sed -e '2,$s/^/prefix/'
Alok Singhal 2014年

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 2015年

2
对于大文件(12 G),awk报告awk: out of memory in readrec 1 source line number 1,但是解决方案sed已成功完成。
jrm

33

您可以在Ex模式下使用Vim:

ex -sc '%s/^/prefix/|x' file
  1. % 选择所有行

  2. s 更换

  3. x 保存并关闭


1
对我来说,我只是用vim和type打开文件:%s/^/prefix/,因为这种策略最终在许多情况下都是有用的
Frank Bryce

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

这是一个使用tsmoreutils命令的高度易读的oneliner解决方案

$ 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

许多Linux发行版默认未安装'ts'。另外,请投票,因为该答案中的结尾“ tr -d''”将删除行中的所有空格,而不仅是删除'ts'添加的空格
Tim Bird

3

尽管我不认为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}

1
使用-used选项来避免缓冲。
Bryan Larsen

2
可以使用unbuffer / stdbuf关闭缓冲,请参见unix.stackexchange.com/q/25372/6205
myroslav 2015年

2

使用ed:

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

这种替代品,每行(,),行(年初^)用prefixwq保存并退出。

如果替换字符串包含斜杠,则可以使用其他定界符s代替:

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

我引用了here-doc分隔符EOE(“ ed的结尾”)以防止参数扩展。在此示例中,它也可以不加引号,但是如果您$的ed脚本中有a ,则避免出现意外情况是一种很好的做法。


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包含任何特殊字符(如斜杠),则此功能将不起作用。
josch

好点...如果你发现你用了很多湿地,你可以使用不同的分隔符与sed的一部分,为这里详述,这将让你在搜索中使用它。其他特殊的sed字符可以通过斜线转义来放入,例如prefix_lines \*
Brad Parks

0

对于BSD / OSX系统上的人们,有一个名为的实用程序lam,是层压板的缩写。lam -s prefix file会做你想要的。我在管道中使用它,例如:

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

...将查找所有文件,对每个文件执行lam,为每个文件添加自己的文件名前缀。(并将输出泵送到fzf进行搜索。)


您是对的,看来这是仅BSD的命令。POSIX用粘贴替换了它,但是粘贴没有添加完整的分隔符字符串的功能。我将更新我的答案。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.