如何使用awk按顺序打印数据?
获得预期输出的标准-如何使用awk按顺序打印数据?,awk,Awk,获得预期输出的标准- 阅读行的第一列,其中“有x个类型”,并且 将其放入变量中,然后移动到下一行并获取第一列 另一个变量中的下一行,并继续下一行 如果此行正好位于包含“有x个类型”的行上方,则 以管道分隔格式打印第一个变量和第二个变量 预期产量- ABC has x types: x.x used by xyzzy x.y.z used by pqr a.b.c.d used by mno PQR has x types: x.x used by xyzzy x.y.z used
- 阅读行的第一列,其中“
,并且 将其放入变量中,然后移动到下一行并获取第一列 另一个变量中的下一行,并继续下一行有x个类型”
- 如果此行正好位于包含“
有x个类型”的行上方,则 以管道分隔格式打印第一个变量和第二个变量
ABC has x types:
x.x used by xyzzy
x.y.z used by pqr
a.b.c.d used by mno
PQR has x types:
x.x used by xyzzy
x.y.z used by pqr
XYZ has x types:
x.x used by xyzzy
p.q.r used by pqr
我试过这个-
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
你能试试下面的吗
awk '$0 ~ /has/ {p=$1}; q=$1; {print p,q}' k
ABC has x types:
ABC ABC
x.x used by xyzzy
ABC x.x
x.y.z used by pqr
ABC x.y.z
a.b.c.d used by mno
ABC a.b.c.d
PQR has x types:
PQR PQR
x.x used by xyzzy
PQR x.x
x.y.z used by pqr
PQR x.y.z
XYZ has x types:
XYZ XYZ
x.x used by xyzzy
XYZ x.x
p.q.r used by pqr
XYZ p.q.r
输出如下
awk '
BEGIN{
OFS=" | "
}
/has/{
if(val && prev){
print val,prev
prev=val=""
}
val=$1
next
}
{
prev=$1
}
END{
if(val && prev){
print val,prev
}
}
' Input_file
编辑:添加GNU
awk
解决方案。用GNUawk
测试和编写。还要提到的是,对于大文件来说,这可能有点慢,因为这将把整个文件作为一行读取
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
awk-vrs=“”-vfs=“\n”
开始{
OFS=“|”
}
{
对于(i=1;i我也使用数组-
awk -v RS="" -v FS="\n" '
BEGIN{
OFS=" | "
}
{
for(i=1;i<=NF;i++){
if($i~/has/){
if(val){
split(val,array1," ")
split($(i-1),array2," ")
print array1[1],array2[1]
val=""
}
val=$i
}
}
delete array1
delete array2
}
' Input_file
awk
中的第三个变量可能是:
awk '/has/ {p=$1} {a[p]=$1} END {for (p in a) print p "|" a[p]}' f
XYZ|p.q.r
PQR|x.y.z
ABC|a.b.c.d
解释
上面的awk
命令有3条规则:
$1~/^[A-Z]+$/{lbl=$1}
如果第一个字段都是大写的,则将文件保存在lbl
(用于标签)。这仅在字段1都是大写时执行
{a[lbl]=$1}
将数组a[lbl]
设置为等于第一个字段(对所有记录执行);以及
END{for(a中的i)print i,“|”,a[i]}
在处理所有记录结束时,循环数组中的每个元素a
输出标签的最后存储值
基本上,您只是将第一个字段存储在a[lbl]
下,其中lbl
是最后一个看到的全大写字段。结果是a[lbl]
保存每个标签下最后一个看到的第一个字段
示例使用/输出
将数据保存在文件中
,然后
awk '$1~/^[A-Z]+$/ {lbl=$1}; {a[lbl]=$1}; END {for(i in a) print i,"|",a[i]}' file
因为你可以用一个大的sed
$ awk '$1~/^[A-Z]+$/{lbl=$1}; {a[lbl]=$1}; END { for(i in a) print i,"|",a[i] }' file
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
下面是另一个带有说明的awk
脚本:
scirpt.awk
输入文件
运行:
输出:
很抱歉,但我实际上一点也不理解你的问题。这里的所有答案都是预期的结果,但我不确定这些答案中的逻辑是否是你想要的逻辑。你如何得到ABC
应该有a.b.c.d
?它与mno
有什么关系?这种关系重要吗?请写下来你想要什么的规则。@kvantour-我已经更新了标准以获得预期的输出,请检查。Downvoter-如果有任何范围,请建议我提高这个问题的质量。千万不要将字母l
用作变量名,因为它看起来太像数字1
(在某些字体中完全无法区分)这样就混淆了你的代码。@EdMorton你说得太对了。回头看这篇文章,1
(一)和'l'
(小写的ell)字体的使用几乎完全相同……糟糕。Will更新为lbl
我曾经在一所大学的实验室里花了几个小时帮助某人调试语法错误,但无法找出问题所在,于是她开始重新键入程序。当她必须按1
键时,我注意到她改按了l
键。当然,这是w问题是。当我问她为什么这样做时,她说这是他们在打字课上教她做的,因为键入l
比键入1
要快。这让我明白了在程序中从1
s中分辨l
s有多难!这会不必要地将整个文件存储到内存中并且在问题的预期输出中不使用您要求的输出分隔符。其中还有各种伪分号,并且不使用两个不同的变量名(p
,然后是k
)同样的道理。最后-变量q
没有任何用处,你可以只做a[p]=$1
,一旦你解决了大部分问题,那么你就剩下了。@EdMorton-谢谢你的建议,先生,这是a[p]=$1
和分号;但是我没有得到这部分不要使用两个不同的变量名(p在身体里,然后是k在最后)为了同样的事情。我相信p和k在这里扮演不同的角色。p
包含了a[]
索引的值,当你在a[]
上写东西的时候,k
包含了a[]
索引的值,当你在a[]上读东西的时候
。两个变量都包含相同的内容-输入的键值用作a[]
的索引。事实上,您使用一个变量来编写a[]
,使用一个变量来读取a[]
没有使它们不同-它们仍然持有/代表相同的东西。不需要使用cat
,因为cat文件| tr'\n'@
=tr'\n'@
。
cat file | tr '\n' '@' | sed 's/@$//;s/ *used by[^@]*//g;s/@\([^@]*has x types:\)/\n\1/g;s/ *has[^\n]*@/ | /g'
$ awk -v OFS=' | ' '/has/{if (NR>1) print key, prev; key=$1} {prev=$1} END{ print key, prev }' file
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r
BEGIN {OFS = " | "} # assign output separator to " | "
/ has / { # on lines with "has"
if (key) print key, val; # print the previous key | value if key exist
key = $1; # capture the recent key from 1st input field
}
{ # on any line
val = $1; # capture the recent value from 1st input field
}
END {print key, val} # output the last key | value pair
ABC has x types:
x.x used by xyzzy
x.y.z used by pqr
a.b.c.d used by mno
PQR has x types:
x.x used by xyzzy
x.y.z used by pqr
XYZ has x types:
x.x used by xyzzy
p.q.r used by pqr
awk -f script.awk input.txt
ABC | a.b.c.d
PQR | x.y.z
XYZ | p.q.r