使用分隔符三重管道符号“|||”逐行合并两个文件

使用分隔符三重管道符号“|||”逐行合并两个文件

我有两个并行文件,具有两种语言的相同行数,并计划使用分隔符逐行合并这两个文件|||。例如,两个文件如下:

文件A:

1Mo 1,1 I love you.
1Mo 1,2 I like you.
Hi 1,3 I am hungry.
Hi 1,4 I am foolish.

文件B:

1Mo 1,1 Ich liebe dich.
1Mo 1,2 Ich mag dich.
Hi 1,3 Ich habe Durst.
Hi 1,4 Ich bin neu.

预期输出是这样的:

1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.

我尝试了paste以下命令:

paste -d "|||" fileA fileB

但返回的输出仅包含一个管道,例如:

1Mo 1,1 I love you. |1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. |1Mo 1,2 Ich mag dich.

有没有办法用牛肚管将每对线分开|||

答案1

POSIX 粘贴:

:|paste -d ' ||| ' fileA - - - - fileB

paste将连接所有输入文件的相应行。这里我们有六个文件、、fileA四个来自标准的虚拟文件-、和fileB

分隔符列表包括一个空格、三个竖线和一个空格,按此顺序将paste循环使用。

对于六个文件的第一行,fileA将与第一个虚拟文件连接(这没什么,感谢无操作:运算符),产生line1-fileA<space>.

第一个虚拟文件将通过管道与第二个虚拟文件 Produce 连接,line1-fileA |然后第二个虚拟文件与第三个虚拟文件 Produce ,line1-fileA ||第三个虚拟文件与第四个虚拟文件 Produce line1-fileA |||

第四个虚拟文件为fileB, 生成line1-fileA ||| line1-fileB.

将对所有行重复这些步骤,为您提供预期的结果。


的使用:|是为了减少打字,主要用在交互式 shell 中。在脚本中,您应该使用:

</dev/null paste -d ' ||| ' fileA - - - - fileB

以防止生成子 shell。

答案2

嗯,这不使用 sed、awk 或 grep,但您可以在 bash 中轻松完成。命令是:

(while IFS= read -r a <&3 && IFS= read -r b <&4; do echo "$a ||| $b"; done) 3<fileA 4<fileB

粘贴的问题在于分隔符是单个字符。您还可以插入单个字符并使用 sed 对其进行转换,但如果该字符已经出现在输入文件中,那么这会很容易出错。

答案3

awk (GNU) 版本

awk '{printf ("%s ||| ", $0); getline < "fileB"; print $0 }' fileA

使用getline中的命令,如果您从指定文件中设置下一条记录,则awk可以$0从下一条输入记录中设置(列的所有变量) 。getline < "filename"$0

getline < "file" 从文件的下一条记录开始设置 $0;设置 NF。


为什么你的尝试没有达到你的预期?从中man paste我们可以读到

-d, --delimiters=LIST
     reuse characters from LIST instead of TABs

它对每一列使用一个分隔符

所以命令
paste -d '|*|*' fileA fileB fileA fileB给我的行是

Hi 1,3 I am hungry.|Hi 1,3 Ich habe Durst.*Hi 1,3 I am hungry.|Hi 1,3 Ich...
Hi 1,4 I am foolish.|Hi 1,4 Ich bin neu.*Hi 1,4 I am foolish.|Hi 1,4 Ich...


我建议避免使用这种解决sed方案,即使它接近您最初的尝试,因为它会将获得的行为修补到您的原始目的:

 paste -d '|' fileA fileB | sed 's/|/|||/g'

为了避免因为你|用新的模式替换每个模式|||但您必须假设|数据中不存在管道符号 ( ),否则你必须处理特殊情况并编写更复杂的代码以避免副作用。


一个变体与这里字符串[1] 构建<<<

 paste -d ' ||| ' fileA - - - - fileB  <<< ''

您设置 5 个分隔符-d ' ||| '(空格、|、|、|、空格)和 4 个虚拟文件 ( - - - -),它们将从空字符串中获取数据''


在 GNU Awk 4.0.1、paste (GNU coreutils) 8.21 和 sed (GNU sed) 4.2.2 上测试

答案4

你也可以用这种方式在Python中做到这一点。

lines1 = [ line.rstrip() for line in open("file1") ]
lines2 = [ line.rstrip() for line in open("file2") ]
for i in xrange((len(lines1))): print lines1[i] + " ||| " + lines2[i]
... 
1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.

相关内容