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