Bash 拆分一个大的txt文件以执行grep-unix
我使用txt文件(unix、shell脚本),这些文件由管道分隔成数百万个字段,而不是由Bash 拆分一个大的txt文件以执行grep-unix,bash,unix,split,grep,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|fie
\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=姓名;field2=姓氏;field3=手机;field4=电子邮件;field5=办公电话;field6=skype
)
当我需要查找字段时(例如field2
),类似grep的命令不起作用(在同一行中)
我认为一个好的解决方案是编写一个脚本,用“\n”分隔每6个字段,然后执行grep。我是对的?多谢各位 用六块一块打印行怎么样
$ 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
$awk'BEGIN{FS=OFS=“|”}{for(i=1;i如果要将文件视为多行,请将\n
设为字段分隔符。例如,要获取第二列,只需执行以下操作:
tr \| \\n < input-file | sed -n 2p
tr\|\\n
要查看哪些列与正则表达式匹配,请执行以下操作:
tr \| \\n < input-file | grep -n regex
tr\|\\n
您可以使用sed
将行拆分为多行:
sed 's/\(\([^|]*|\)\{6\}\)/\1\n/g' input.txt > output.txt
说明:
- 我们必须使用
(){}
的大反斜杠转义,这使得代码稍微不可读
- 但简而言之:
s/
和/\1
之间的术语([^ |]*.{6})
(为可读性而删除反斜杠)将匹配:
[^ |]*
除“|”以外的任何字符,重复多次
|
后跟一个“|”
- 上述内容显然是一列,并与随附的论文
(
和)
- 整个组重复6次
{6}
- 这一部分又与随附的论文
(
和)
组合在一起,形成一整套
本学期的其余部分很容易阅读:
- 将上述(6个字段的整个数据集)替换为
\1\n
,即/
和/g
之间的部分
\1
指sed表达式中的“第一”组(启动的“第一”组,因此它是由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|
这就是正则表达式的工作原理:
[^ |]
是任何非
字符
[^ |]\+
是至少一个非
字符的序列
[^ |]\+
是至少一个非
字符后跟
的序列
\([^ |]\+\124;\)
是至少一个非
字符的序列,后跟一个
,组合在一起
\([^ |]\+\\}{6\}
是6个连续的此类组
\(\([^ |]\+\\{6\}\)
是6个连续的此类组,分组在一起
替换只需按6组的顺序进行,并在末尾添加一个换行符。使用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|
$cat a
田1A |田2A |田3A |田5A |田6A |田1D |田2D |田3D |田4D |田5D |田6D |田1M |田2M |田3M |田4M |田5M |田6M |田1Z 1246ZӞ|
$awk-F“|”{for(i=1;i下面是如何使用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
调整为适合您的字段数。只是想知道,为什么您的文本文件是这样构建的?为什么有人会否决这个问题?因为OP必须以愚蠢的格式处理一个文件?我收到了这个文件。就像一个文件归档器,保存所有处理过的信息:Dsed
通常是这是一个独立的二进制文件,因此不依赖于您正在使用的shell。@umläute:您是对的,但是转义括号和
可能有不同的要求,所以我认为最好提及这一点。是的,第二个是我所需要的!谢谢。+1尽管修改ORS
awk-v RS=“|”更好{ORS=(NR%7?”|“:“\n”)}1'文件
谢谢。将“|”更改为RS
嗯,很好!我知道这个问题可以用NR/RS技巧:)