[英]Split a big txt file to do grep - unix
我使用txt文件(unix,shell脚本),这些txt文件通过管道用数百万个字段分隔,而不用\\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
)
当我需要查找一个字段(例如field2
)时,像grep这样的命令不起作用(在同一行中)。
我认为一个好的解决方案可以是使用“ \\ n”分割每6个字段的脚本,然后再执行grep。 我是正确的? 非常感谢你!
用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|
在这里,您可以轻松设置行的长度。
希望这可以帮助 !
您可以使用sed
将行拆分为多行:
sed 's/\(\([^|]*|\)\{6\}\)/\1\n/g' input.txt > output.txt
说明:
我们必须对(){}
使用大量的反斜杠转义,这会使代码有些难以理解。
简而言之:
s/
和/\\1
之间s/
(([^|]*|){6})
术语(([^|]*|){6})
为了可读性删除了反斜杠)将匹配:
[^|]*
除'|'以外的任何字符,重复多次
|
后跟一个“ |”
上面的内容显然是一栏,并与括起来的括号(
和)
组合在一起
整个组重复6次{6}
然后再将其与括起来的括号(
和)
组合在一起,形成一个完整的集合
该术语的其余部分很容易理解:
将上述(6个字段的整个数据集)替换为\\1\\n
( /
和/g
之间的部分)
\\1
表示sed-expression中的“第一个”组(已启动的“第一个”组,因此是6个字段的整个数据集)
\\n
是换行符
因此,请自行替换6个字段的整个数据集,然后再换行
并重复这样做(结尾的g
)
您可以使用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个组的顺序进行,并在末尾添加换行符。
这是我将如何使用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
调整为适合您的字段数即可。
怎样将行打印在六个块上?
$ 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
最终写出新行时,就完成了。 如果要将文件视为多行,请使用\\n
字段分隔符。 例如,要获取第二列,只需执行以下操作:
tr \| \\n < input-file | sed -n 2p
要查看哪些列与正则表达式匹配,请执行以下操作:
tr \| \\n < input-file | grep -n regex
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.