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

我有一个文件如下:

line1
line2
line3

我想要得到:

prefixline1
prefixline2
prefixline3

我可以编写Ruby脚本,但如果我不需要这样做会更好。

prefix将包含/。它是一个路径,例如/opt/workdir/

484163 次浏览
# 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/'
awk '$0="prefix"$0' file > new_file

在awk中,默认的操作是'{print $0}'(即打印整行),因此上述操作相当于:

awk '{print "prefix"$0}' file > new_file

使用Perl(就地替换):

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

使用shell:

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

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

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

  2. s取代

  3. x保存并关闭

如果你有Perl:

perl -pe 's/^/PREFIX/' input.file

虽然我不认为pierre有这种顾虑,但我需要一种解决方案,它不会延迟来自文件的实时“尾部”的输出,因为我想同时监视几个警报日志,并在每行之前加上各自日志的名称。

不幸的是,sed、cut等引入了太多的缓冲,使我无法看到最新的行。Steven Penny建议使用nl-s选项很有趣,测试证明它没有引入我担心的不必要的缓冲。

不过,使用nl有几个问题,与去除不需要的行号有关(即使你不关心它的美观性,也可能在某些情况下使用额外的列是不可取的)。首先,使用“cut”去除数字再次引入了缓冲问题,因此它破坏了解决方案。其次,使用“-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}

如果你的前缀有点复杂,就把它放在一个变量中:

prefix=path/to/file/

然后,你传递这个变量,让awk来处理它:

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

下面是一个使用这个答案中的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

艾德:使用

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

对于每一行(,),这将用prefix代替行(^)的开头。wq保存并退出。

如果替换字符串包含斜杠,则可以为s使用不同的分隔符:

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

我引用了here-doc分隔符EOE(“end of ed”),以防止参数展开。在这个例子中,它也可以不带引号工作,但如果你的ed脚本中有$,这是一个很好的实践,可以防止意外。

对于在BSD/OSX系统上的人来说,有一个名为lam的实用程序,是laminate的缩写。lam -s prefix file将做你想做的。我把它用在管道上,例如:

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

...这将找到所有的文件,exec lam对他们每个,给每个文件自己的文件名的前缀。(并将输出泵到fzf进行搜索。)

下面是一个高度可读的联机解决方案,使用moreutils中的ts命令

$ 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

使用,(与模式匹配的整个输入部分”):

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

或者使用反向引用:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt
  1. 你也可以使用反向引用技术来实现这一点

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. You can also use with awk like this

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


YourPrefix=blabla


YourPath=C:\path


for /f "tokens=*" %%a in (!YourPath!\longfile.csv)     do (echo !YourPrefix!%%a) >> !YourPath!\Archive\output.csv

如果您需要在每行具有特定字符串的开头预先添加文本,请尝试以下操作。在下面的例子中,我在每一行有单词"rock"的开头添加#;在里面。

sed -i -e 's/^.*rock.*/#&/' file_name

使用Pythonize (pz):

pz '"preix"+s' <filename

在bash的命令行上使用for循环的简单解决方案:

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

将输出保存到一个文件:

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

你可以使用AWK来实现

echo example| awk '{print "prefix"$0}'

awk '{print "prefix"$0}' file.txt > output.txt

后缀:awk '{print $0"suffix"}'

对于前缀和后缀:awk '{print "prefix"$0"suffix"}'