Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 搜索文件行中的特定字段_Bash_Shell - Fatal编程技术网

Bash 搜索文件行中的特定字段

Bash 搜索文件行中的特定字段,bash,shell,Bash,Shell,我有一个包含以下数据的文件: 0000380000000101 0000650000000201 0000650000000301 0000650000000401 0001000000000101 0001000000000201 ……等等。我想处理这些数据,以便得到如下输出 000065 0000000201 0000000301 0000000401 000100 0000000101 0000000201 当000065重复三次时,在输出中我希望000065只出现一次,而出现00

我有一个包含以下数据的文件:

0000380000000101
0000650000000201
0000650000000301
0000650000000401
0001000000000101
0001000000000201
……等等。我想处理这些数据,以便得到如下输出

000065 0000000201 0000000301 0000000401  
000100 0000000101 0000000201
当000065重复三次时,在输出中我希望000065只出现一次,而出现000065的每个条目中的相应字节都应该打印出来。因为,000038只出现一次,所以我不希望输出中出现这个。在本例中,数据(即000065或000038恰好是3个字节,尽管它可以是任何长度,而在这之后的字节(如0000000 401)将是固定长度的,即5个字节)。我希望最好使用shell脚本或c来完成这项工作。请让我知道我该怎么做。awk在这里有帮助吗? 任何帮助都将不胜感激。以下是从实际文件中获取的数据,我要处理:

0000000000000101
0000000000000201
0000000000000301
0000000000000401
0000380000000101
0000650000000201
0000650000000301
0000650000000401
0001000000000101
0001000000000201
0001000000000301
0001000000000401
0038d30000000101
00652e0000000201
00652e0000000301
00652e0000000401
008d750000000101
008d750000000201
008d750000000301
008d750000000401
0100010000000101
0100010000000201
0100010000000301
0100010000000401
01008d0000000101
01008d0000000201
01008d0000000301
01008d0000000401
01a8c00000000101
01a8c00000000201
01a8c00000000301
01a8c00000000401
0264010000000101
0264010000000201
0264010000000301
0264010000000401
0615df0000000101
0615df0000000201
0615df0000000301
0615df0000000401
07dd940000000101
07dd940000000201
07dd940000000301
07dd940000000401
0900000000000101
0900000000000201
0900000000000301
0900000000000401
15dfc70000000101
15dfc70000000201
15dfc70000000301
15dfc70000000401
1ecf090000000101

您的数据是固定宽度的,因此您可以使用
gawk

$ gawk -v FIELDWIDTHS='6 10' 'NR!=1 && x==$1""{printf(" %s", $2); next}; {x=$1""; printf("%s%s %s", NR==1?"":"\n", $1, $2)}; END{print ""}' input.txt | sed '/^[0-9a-f]* [0-9a-f]*$/d'
000000 0000000101 0000000201 0000000301 0000000401
000065 0000000201 0000000301 0000000401
000100 0000000101 0000000201 0000000301 0000000401
00652e 0000000201 0000000301 0000000401
008d75 0000000101 0000000201 0000000301 0000000401
010001 0000000101 0000000201 0000000301 0000000401
01008d 0000000101 0000000201 0000000301 0000000401
01a8c0 0000000101 0000000201 0000000301 0000000401
026401 0000000101 0000000201 0000000301 0000000401
0615df 0000000101 0000000201 0000000301 0000000401
07dd94 0000000101 0000000201 0000000301 0000000401
090000 0000000101 0000000201 0000000301 0000000401
15dfc7 0000000101 0000000201 0000000301 0000000401

这可能适用于您(sed可以吗?):


具有
字段宽度的awk是一种方法,如kev所示

以下是仅适用于awk的另一种方式(oneliner):

awk 'BEGIN{FS=""} 
  {for(i=1;i<=6;i++) x=x$i; y=$0; gsub("^"x,"",y);a[x]=a[x]?a[x]" "y:y;  x="";}
   END{for(t in a)print t" "a[t]}' yourFile
awk'开始{FS=”“}

{对于(i=1;i您可以执行以下awk命令(在Linux和Mac上测试):

输出:

000065 50000000401 50000000301 50000000201 
000100 00000000201 00000000101 

首先,通过以下管道传输数据文件:

awk '{suffixLen = 10; print substr($0, 1, length($0) - suffixLen)" "substr($0, length($0) - suffixLen + 1, length($0))}'
awk '{if ($1 in values) {values[$1] = values[$1]" "$2} else {values[$1] = $1" "$2}}END{for (v in values) print values[v]}'
后缀变量是尾随字符的(固定)数量:每个字符2个字节=10。这将把输入字符串分成两个字段,用空格分隔

然后通过这个管道:

awk '{suffixLen = 10; print substr($0, 1, length($0) - suffixLen)" "substr($0, length($0) - suffixLen + 1, length($0))}'
awk '{if ($1 in values) {values[$1] = values[$1]" "$2} else {values[$1] = $1" "$2}}END{for (v in values) print values[v]}'

结果的正确排序留给读者作为练习。

对不起,我只在
Ubuntu
@kev:非常感谢。我忘了提一件事。输入文件中的数据是按顺序排序的。这可以用来获得所需的输出吗。此外,我在以下数据上使用了这个cmd:@kev:再次感谢。一需要更多信息。我想使用你在c中使用系统函数告诉我的cmd。你能告诉我怎么做吗。我想在这里给出fieldwidth ie 6和10的值作为输入。我使用了sprintf(cmd,“gawk-v FIELDWIDTHS='%d%d''NR!=1&&x=$1{printf('%s',$2);next};{x=$1;printf(“%s%s%s,NR==1?”:“\n”,$1,$2)};END{print”“}nbyte2 | sed'/^[0-9a-f]*[0-9a-f]*$/d',n,m);但它给了我错误。@kev:在你提到的上述gawk cmd中,我遇到了一个问题。我使用了以下数据
00E246B501000F06 00e248380100002065 00e251540100000460 00e254bc01000022a9 00E25E0100001E4E
,并使用了cmd`gawk-v FIELDWIDTHS='8 10''NR!=1&&x=$1{printf(“%s”,“$2”);next};{x=$1;printf(“%s%s%s%s”,NR==1?”:“\n”,$1,$2)};结束{print”“}输入数据文件
。但令我惊讶的是,输出结果是
00e246b5 0100000f06 00e24838 0100002065 010000460 00e254bc 01000022a9 00e25e0e 0100001e4e`。你能告诉我为什么会这样吗。再次感谢。对不起,这是个错误。你可以用
x=$1”“
x=$1”来修复它。”“
。只需在
$1
之后添加
,即可使awk比较字符串。
awk '{suffixLen = 10; print substr($0, 1, length($0) - suffixLen)" "substr($0, length($0) - suffixLen + 1, length($0))}'
awk '{if ($1 in values) {values[$1] = values[$1]" "$2} else {values[$1] = $1" "$2}}END{for (v in values) print values[v]}'