拆分一个大文本文件来做grep - unix

时间:2014-05-26 13:00:17

标签: bash unix split grep

我使用txt文件(unix,shell脚本)工作,这些文件由管道分隔数百万字段,而不是由\n\r分隔。 像这样的东西:

field1a|field2a|field3a|field4a|field5a|field6a|[...]|field1d|field2d|field3d|field4d|field5d|field6d|[...]|field1m|field2m|field3m|field4m|field5m|field6m|[...]|field1z|field2z|field3z|field4z|field5z|field6z|

所有文字都在同一行。

每个文件的字段数都是固定的。

(在本例中我有field1=name; field2=surname; field3=mobile phone; field4=email; field5=office phone; field6=skype

当我需要找到一个字段(ex field2)时,像grep这样的命令不起作用(在同一行)。

我认为一个好的解决方案可以做一个脚本,用#34; \ n"分隔每6个字段。并做了一个grep。我对吗?非常感谢你!

6 个答案:

答案 0 :(得分:3)

使用awk:

$ cat a
field1a|field2a|field3a|field4a|field5a|field6a|field1d|field2d|field3d|field4d|field5d|field6d|field1m|field2m|field3m|field4m|field5m|field6m|field1z|field2z|field3z|field4z|field5z|field6z|



$ awk -F"|" '{for (i=1;i<NF;i=i+6) {for (j=0; j<6; j++) printf $(i+j)"|"; printf "\n"}}' a

field1a|field2a|field3a|field4a|field5a|field6a|
field1d|field2d|field3d|field4d|field5d|field6d|
field1m|field2m|field3m|field4m|field5m|field6m|
field1z|field2z|field3z|field4z|field5z|field6z|

在这里,您可以轻松设置行的长度。

希望这有帮助!

答案 1 :(得分:2)

您可以使用sed将行分成多行:

 sed 's/\(\([^|]*|\)\{6\}\)/\1\n/g' input.txt > output.txt

说明:

  • 我们必须使用(){}的重反斜杠转义,这会使代码稍微不可读。

  • 但简而言之:

    • (([^|]*|){6})s/之间的/\1(为了便于阅读而删除反斜杠)一词将匹配:

      • [^|]*任何字符,但“|”,重复多次

      • |后跟“|”

      • 上面显然是一列,它与封闭的parantheses ()

      • 组合在一起
      • 整个小组重复6次{6}

      • 然后再将其与封闭的parantheses ()组合在一起,形成一整套

该术语的其余部分易于阅读:

  • 将上述(6个字段的整个数据集)替换为\1\n//g之间的部分

  • \1是指sed表达式中的“第一个”组(启动的“第一个”组,因此它是6个字段的整个数据集)

  • \n是换行符

  • 所以替换6个字段的整个数据集,然后换行换行符

  • 并重复执行此操作(尾随g

答案 2 :(得分:2)

您可以使用sed将每第6个|转换为换行符。

在我的tcsh版本中,我可以这样做:

sed 's/\(\([^|]\+|\)\{6\}\)/\1\n/g' filename

考虑一下:

> cat bla
a1|b2|c3|d4|

> sed 's/\(\([^|]\+|\)\{6\}\)/\1\n/g' bla
a1|b2|
c3|d4|

这就是正则表达式的工作原理:

  • [^|]是任何非|字符。
  • [^|]\+是至少一个非|字符的序列。
  • [^|]\+|是至少一个非|字符后跟|的序列。
  • \([^|]\+|\)是至少一个非|字符后跟|的序列,组合在一起
  • \([^|]\+|\)\{6\}是连续6个这样的群体。
  • \(\([^|]\+|\)\{6\}\)是连续6个这样的群组,组合在一起。

替换只需要6个组的序列,并在最后添加换行符。

答案 3 :(得分:2)

以下是我使用awk

的方法
awk -v RS="|" '{printf $0 (NR%7?RS:"\n")}' file
field1a|field2a|field3a|field4a|field5a|field6a|[...]
field1d|field2d|field3d|field4d|field5d|field6d|[...]
field1m|field2m|field3m|field4m|field5m|field6m|[...]
field1z|field2z|field3z|field4z|field5z|field6z|

只需将NR%7字段调整为适合您的字段数。

答案 4 :(得分:1)

如何在六块街区打印线条?

$ awk 'BEGIN{FS=OFS="|"} {for (i=1; i<=NF; i+=6) {print $(i), $(i+1), $(i+2), $(i+3), $(i+4), $(i+5)}}' file
field1a|field2a|field3a|field4a|field5a|field6a
field1d|field2d|field3d|field4d|field5d|field6d
field1m|field2m|field3m|field4m|field5m|field6m
field1z|field2z|field3z|field4z|field5z|field6z

解释

  • BEGIN{FS=OFS="|"}将输入和输出字段分隔符设置为|
  • {for (i=1; i<=NF; i+=6) {print $(i), $(i+1), $(i+2), $(i+3), $(i+4), $(i+5)}}循环浏览6个块上的项目。每次打印其中六个。当print最终写完一个新行时,你就完成了。

答案 5 :(得分:1)

如果要将文件视为多行,请将\n作为字段分隔符。例如,要获取第二列,只需执行:

tr \| \\n < input-file | sed -n 2p

要查看哪些列与正则表达式匹配,请执行:

tr \| \\n < input-file | grep -n regex