我有一个包含如下字符串的文件。
F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315
字符串由标记(在本例中为“F”和数字)划分。在本例中,标记为F1
, F2
, F3
, F4
, F5
,F6
和F7
。
我想打印后面的 5 个字符F2
和后面的 6 个字符,F6
并用空格分隔,以便结果是
B3094 BC313D
这是我的尝试,尽管它打印成两行而不是一行。如何将两个值都放在一行上。
$ echo F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315 | \
awk '{match($0,/F2/); print substr($0, RSTART +2, RLENGTH +3);} \
{match($0,/F6/); print substr($0, RSTART +2,RLENGTH +4);}'
答案1
您非常接近可行的解决方案。这是一种方法(为了便于阅读而格式化):
awk '{
match($0,/F2/);
a=substr($0, RSTART +2, RLENGTH +3);
match($0,/F6/);
b=substr($0, RSTART +2,RLENGTH +4);
print a" "b
}'
在本例中,我将采用您的两个substr()
函数并将它们分配给变量,而不是直接打印它们,然后将它们设置为在最后同时打印。通过在单个打印调用中打印它们,awk
仅在行尾添加一个换行符,而不是在该行的每个部分之后添加,这就是将结果分成两行的原因。
bash:~$ echo F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315 | awk '{match($0,/F2/); a=substr($0, RSTART +2, RLENGTH +3); match($0,/F6/); b=substr($0, RSTART +2,RLENGTH +4); print a" "b}'
B3094 BC313D
答案2
如果您知道标记是有序的,那么您可以将它们用作字段分隔符:Fn
echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' |
awk -F'(F2|F6)' '{print substr($2,1,5), substr($3,1,6)}'
B3094 BC313D
或者,拆分所有标记并对字段进行相应编号Fn
echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' |
awk -F'F[0-9]' '{print substr($3,1,5), substr($7,1,6)}'
B3094 BC313D
(在这种情况下,substr
如果您只想要下一个的所有内容,您可能根本不需要- 从您的问题描述中不清楚)。Fn
使用 GNU Awk,您可以捕获单个模式中的两个子字符串并通过可选match
数组访问它们:
echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' |
gawk 'match($0, /F2(.{5}).*F6(.{6})/, a) {print a[1], a[2]}'
B3094 BC313D
或者,使用 Perl,您可以使用后向捕获标记后的字符:
echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' |
perl -lne 'print join " ", /(?<=F2).{5}|(?<=F6).{6}/g'
B3094 BC313D
或者
echo 'F1B308F2B3094F3B310F4B317CF5B312F6BC313DF7B315' |
perl -lne 'print "$1 $2" if /(?<=F2)(.{5}).*?(?<=F6)(.{6})/g'
B3094 BC313D
答案3
perl -lne ' $, = $"; print /(?=.*F2(.{5}))(?=.*F6(.{6}))/' input-file.txt
无论哪个,F2
或者F6
在当前记录中出现得更早,F2
上面的内容都将打印 的以下数字F6
。
$, = OFS
$" = double quoted separator = single space