合并到 Unix 中

合并到 Unix 中

我有一个以竖线 ( |) 作为分隔符的 CSV 文件,如下所示,我需要在 Unix 中应用合并技术。该文件包含数十万条记录(四个字段),但为了便于阅读,我只给出了五个记录。

field1 |field2 | field3 |field4|
1|abc|def|ghi|
4|ijk|
|lmn|
5||opq|rst|
8|
uvw||xyz|
10|hjg|jsh|nbm|

我希望输出结果为

field1|field2|field3|field4|
1|abc|def|ghi|
4|ijk||lmn|
5||opq|rst|
8|uvw||xyz|
10|hjg|jsh|nbm|

答案1

使用 GNU sed:

sed ':loop /\(.*|\)\{4\}.*/ !{N; s/\n//; b loop}; s/ *| */|/g' file

该命令剖析:

:loop

:信号表示我们可以用于分支的标签。 “loop”只是我为标签选择的名称。

/\(.*|\)\{4\}.*/

是一个行选择器正则表达式,匹配包含 4 个管道符号的行,每个管道符号前面允许有零个或多个任意字符 ( .*|),最后一个管道后面允许有零个或多个任意字符。

!{ ... }

将括号中的命令应用到执行过的任何行不是匹配之前的正则表达式。

N; s/\n//; b loop

N连接当前行模式空间带有换行符和源文件中的下一行,然后s/\n//删除换行符并b loop分支回我们在开始时定义的标签,因此连接的行将再次与正则表达式进行比较。

最后

s/ *| */|/g

将在输出之前应用于模式空间中的任何行。这将删除管道符号周围的所有空格。

答案2

我假设您不想要所有这些空行。

$ cat file
1|abc|def|ghi|
4|ijk|
|lmn|
5||opq|rst|
8|
uvw||xyz|
10|hjg|jsh|nbm|

$ awk -F'|' '{while (NF < 5) {getline nextline; $0 = $0 nextline}}1' file
1|abc|def|ghi|
4|ijk||lmn|
5||opq|rst|
8|uvw||xyz|
10|hjg|jsh|nbm|

问题编辑更新:删除字段分隔符周围的空格

awk -F'[[:blank:]]*[|][[:blank:]]*' -v OFS='|' '
    {while (NF < 5) {getline nextline; $0 = $0 nextline}; $1=$1; print} 
' file

答案3

如果可以选择使用 Vim:

vim -Nesc 'g!/\(.*|\)\{4\}$/j!' -cwq input.txt
  • -Nes以脚本模式运行 Vim,更容易实现自动化
  • -c ...打开文件后运行 Vim 命令
  • g!/\(.*|\)\{4\}$/j!- 每行:g, 那 !match /\(.*|\)\{4\}$/(匹配 4 个管道的正则表达式,由任何东西分隔),将下一行连接到它(:j)。
  • wq- 保存并退出。

相关内容