将一个文件的单值内容作为附加列添加到另一个文件

将一个文件的单值内容作为附加列添加到另一个文件

我有两个文件。一个包含多个列和行,而另一个仅包含一个值:

  • 文件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 filecat "$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 处理file1file2输入(而不是通过 shell 变量传递)应该消除了有关正确转义输入的许多担忧。

https://docs.raku.org/routine/subst
https://www.raku.org

相关内容