我有两个文件。一个包含多个列和行,而另一个仅包含一个值:
- 文件1:
abc def ghi jkl
- 文件2:
hello
我想添加另一列,file1
该列始终包含 中找到的值file2
。因此,输出应该如下所示:
abc def hello
ghi jkl hello
谁能帮我做到这一点吗?
答案1
您可以使用 获取文件的最后一行tail
,然后将其作为外部变量传递给awk
,告诉awk
打印每一行和变量:
$ awk -v s="$(tail -n1 file2)" '{print $0,s}' file1
abc def hello
ghi jkl hello
file2
请注意,这假设 i) 您想要;的最后一行如果不是这种情况,您可以替换tail -n1 file
为cat "$file"
, 和 ii)file2
不包含转义序列(请参阅如何在 awk 脚本中使用 shell 变量?上)。
答案2
无论字符串是什么,这都会起作用file2
:
$ awk 'NR==FNR{x=$0; next} {print $0, x}' file2 file1
abc def hello
ghi jkl hello
或者如果您愿意并且 file2 中的字符串不能包含反斜杠(-v
解释转义序列):
$ awk -v x="$(< file2)" '{print $0, x}' file1
abc def hello
ghi jkl hello
区别如下:
$ cat file2
hello\there
$ awk 'NR==FNR{x=$0; next} {print $0, x}' file2 file1
abc def hello\there
ghi jkl hello\there
$ awk -v x=$(< file2) '{print $0, x}' file1
abc def hello here
ghi jkl hello here
答案3
由于它是您要添加到那里的常量字符串,因此会想到使用 sed,但需要注意的是要添加的字符串嵌入在 sed 的命令行中,因此 sed 专门处理的任何内容都不会按原样进行。例如,a/
将用于终止s///
命令,并将&
被模式部分替换。
$ str=$(cat file2)
$ sed -e "s/\$/ $str/" file1
abc def hello
ghi jkl hello
参见例如讨论:替换文件中可能包含斜杠的模式的第一次出现
与 awk 类似,尽管这也不像人们想象的那样与内容无关,因为对于使用 设定的字符串-v
,awk 处理 C 风格的反斜杠转义,因此字符串foo\tbar
将变成,这可能是也可能不是您想要的。foo[tab]bar
$ str=$(cat file2)
$ awk -v str="$str" '{print $0 " " str}' < file1
abc def hello
ghi jkl hello
参见例如:在 awk 中使用 shell 变量
或者,我想你也可以使用其他工具,尽管这有点鲁布·戈德堡式的。我不知道是什么让我做出这样的决定:
$ paste file1 <( yes "$(cat file2)" ) | head -n "$(wc -l < file1)"
abc def hello
ghi jkl hello
答案4
使用 Raku(以前称为 Perl_6)
raku -e 'my $str="/path/to/file2".IO.lines(1); .subst(/(^.*$)/, {$0,$str}).put for lines;' file1
简而言之,第一行(大概是唯一一行)file2
被读入变量$str
,然后file1
逐行分析,subst
-ituting(实际上是附加)$str
到每行的末尾,甚至是空白行。要将行为更改为仅将“hello”添加到包含字符的行的末尾,请更改(^.*$)
为(^.+$)
。
输入示例:
- 文件1:
abc def ghi jkl
- 文件2:
hello
示例输出:
abc def hello
ghi jkl hello
让 Raku 处理file1
和file2
输入(而不是通过 shell 变量传递)应该消除了有关正确转义输入的许多担忧。