我有一个名为File-1
.我必须匹配一个模式DATA_POINTS
,然后在跳过一行后我想打印以下行的第六列。
File-1
例子:here ! some other data exist but all of them are totally different from the below data! In simple words following data is completely unique. DATA_POINTS 12 0.0000000000 0.0000000000 0.0000000000 20 ! A 0.5000000000 0.5000000000 0.0000000000 20 ! B 0.7500000000 0.5000000000 0.2500000000 20 ! C 0.7500000000 0.3750000000 0.3750000000 20 ! D 0.0000000000 0.0000000000 0.0000000000 20 ! E 0.5000000000 0.5000000000 0.5000000000 20 ! F 0.6250000000 0.6250000000 0.2500000000 20 ! U 0.7500000000 0.5000000000 0.2500000000 20 ! W 0.5000000000 0.5000000000 0.5000000000 20 ! L 0.7500000000 0.3750000000 0.3750000000 20 ! K 0.6250000000 0.6250000000 0.2500000000 20 ! U 0.5000000000 0.5000000000 0.0000000000 20 ! X
- 所需输出
S1 = A S2 = B S3 = C S4 = D S5 = E S6 = F S7 = U S8 = W S9 = L S10= K S11= U S12= X
该模式DATA_POINTS
不会在文件中重复,并且需要精确匹配。
最近的解决方案
我从另一个 qsn 得到这个命令。如果第 6 列位于同一行模式中,则此方法有效
awk '/DATA_POINTS/{i==0 ; i++; getline; print "S"i"=", $6}' File-1
答案1
以下awk
程序应该完成这项工作:
awk 'BEGIN{n=-1}
n>0{printf "S%-*d=%s\n",w,++i,$6; if (i==n) {i=0;n=-1}}
n==0{n=$1;w=length($1)}
$0=="DATA_POINTS"{n=0}' file
这会:
- 一开始
n
用初始化一个“状态标志”-1
,意思是“在数据块之外”。 DATA_POINTS
当遇到仅由字符串组成的行时,设置n
为0
,意思是“下一行包含数据点数”- 当
n
为零时,该行的内容被解释为数据点的数量并存储在 中n
。该数字的长度(以字符/数字为单位)存储在w
用于稍后格式化输出的字段中。 - 当
n
大于 时0
,表明我们位于“数据”块内,使用计数变量i
(使用格式设置为固定宽度w
并按输出示例中的左侧调整)和该行的第 6 个字段打印“键”,i
直到等于n
,此时n
重置为-1
这可能比您需要的功能更多,因为它可以处理不在文件末尾的数据块(它尊重标头中指定的数据行数,而不是只读取到文件末尾) )。
笔记目前查找的方法DATA_POINTS
是全字符串匹配,如果实际字符串可以包含特殊字符,这是最稳健的方法。如果您想要部分字符串匹配或正则表达式匹配,请使用
index($0,"DATA_POINTS") { ... }
或(如您的示例所示)
/DATA_POINTS/ { ... }
此外,如果您想防止误解空行,请将n>0
和分别替换n==0
为n>0&&NF
和n==0&&NF
。
答案2
$ awk '/DATA_POINTS/{c=3} c&&!--c{f=1} f{printf "S%d = %s\n", ++s, $6}' file
S1 = A
S2 = B
S3 = C
S4 = D
S5 = E
S6 = F
S7 = U
S8 = W
S9 = L
S10 = K
S11 = U
S12 = X
要从匹配行(含)的第 27 行而不是第 3 行开始打印,只需将 3 更改为 27。
看https://stackoverflow.com/questions/17908555/printing-with-sed-or-awk-a-line-following-a-matching-pattern/17914105#17914105有关上述方法的更多信息以及赛后做某事的更多方法。
答案3
利用范围运算符,
。开始是数据点行,结束是 eof。
awk '
/DATA_POINTS/,0 {
if ( /DATA_POINTS/ ) {
getline; next
}
printf "S%-2d=%s%s\n", ++k, OFS, $6
}
' file
答案4
这是一个单行解决方案,使用 sed 提取行号,使用 bc 加 2,使用 tail 提取数据块,最后使用 awk 获取正确的列。可能不是最干净或最简单的解决方案,但对我来说,它比仅使用 awk 更清晰。
sed -n '/DATA_POINTS/=' $file | xargs -i echo '{}+2' | bc | xargs -i tail -n+{} $file | awk '{print $6}'