Jac*_*cky 1 awk text-processing
这是一个示例文本。(它的名称是 20210622_090009)
nvmeSerial Endpoint nvmeSpeed nvmeWidth
================================================================================
nvme0n1 c7:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme1n1 c8:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme2n1 c9:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme3n1 ca:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme4n1 85:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme5n1 86:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme6n1 87:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme7n1 88:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme8n1 41:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme9n1 42:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme10n1 43:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme11n1 44:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme12n1 45:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme13n1 46:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme14n1 47:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme15n1 48:00.0 Width x2 (downgraded)
nvme16n1 01:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme17n1 02:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme18n1 03:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme19n1 04:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme20n1 05:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme21n1 06:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme22n1 07:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme23n1 08:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme24n1 09:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme25n1 0a:00.0 Speed 32GT/s (ok) Width x2 (downgraded)
Run Code Online (Sandbox Code Playgroud)
这是脚本:
#! /bin/bash
IFS_old="$IFS"
IFS=$'\n'
for line in $(cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}' )
do
echo "$line"
done
IFS="$IFS_old"
exit 0
Run Code Online (Sandbox Code Playgroud)
脚本输出是
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s
Run Code Online (Sandbox Code Playgroud)
我想抓取 nvmeSpeed(Ex:8GT/s) 无论速度是否有数字。
如您所见, nvmeSpeed innvme15n1是一个空格。
并且输出不显示。
我的问题是:
如何 awk 一个空格成为 for 循环输入?
cas*_*cas 11
awk一个人就可以做到这一切。您不需要 shell 脚本包装器,当然也不需要像cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}')那样的巴洛克式的东西,并且应该避免在任何地方使用 shell while-read 循环(或在 awk 或 perl 等语言的输出上使用 for 循环)可能(请参阅为什么使用 shell 循环来处理被认为是不好的做法的文本?原因)。
经验法则:如果你发现自己在想“我想迭代 awk 的输出”,你应该改变你的想法“我几乎肯定应该只用 awk 来做这件事”,或者一个 shell 包装器为 awk 设置输入和输出重定向做批量处理工作。perl 和大多数其他语言也是如此。任何其他语言都可以比 shell 更好地完成处理工作,而尝试使用 shell 只会使您的工作变得更加困难。
无论如何,如果正好有 8 列 ( NF == 8) ,以下脚本将打印第 4 列。如果少于 8 列 ( NF < 8),则打印一个空行。在这两种情况下,它都会忽略每个输入文件开头的两个标题行(它可以处理一个或多个文件名参数 FNR < 3 {next}。在 awk 中,NR 是读取的总行数,而 FNR 是当前文件的行号) .
$ awk 'FNR < 3 {next}; NF == 8 {print $4}; NF < 8 {print ""}' 20210622_090009.txt
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s
Run Code Online (Sandbox Code Playgroud)
看起来您有固定宽度的字段,因此,将 GNU awk 用于 FIELDWIDTHS 和 gensub():
$ awk -v FIELDWIDTHS='16 12 24 *' '
NR>2 {
gsub(/^ *| *$/,"",$3)
print gensub(/.* ([^ ]+) .*/,"\\1",1,$3)
}
' file
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s
Run Code Online (Sandbox Code Playgroud)
上面首先通过每个字段的宽度来标识每个字段的内容:
$ cat file
nvmeSerial Endpoint nvmeSpeed nvmeWidth
================================================================================
nvme0n1 c7:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme1n1 c8:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
nvme15n1 48:00.0 Width x2 (downgraded)
nvme25n1 0a:00.0 Speed 32GT/s (ok) Width x2 (downgraded)
Run Code Online (Sandbox Code Playgroud)
$ cat tst.awk
BEGIN { FIELDWIDTHS="16 12 24 *" }
NR != 2 {
print
for (i=1; i<=NF; i++) {
gsub(/^ *| *$/,"",$i)
print "\t" i, "<" $i ">"
}
print "-----"
}
Run Code Online (Sandbox Code Playgroud)
$ awk -f tst.awk file
nvmeSerial Endpoint nvmeSpeed nvmeWidth
1 <nvmeSerial>
2 <Endpoint>
3 <nvmeSpeed>
4 <nvmeWidth>
-----
nvme0n1 c7:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
1 <nvme0n1>
2 <c7:00.0>
3 <Speed 8GT/s (ok)>
4 <Width x2 (downgraded)>
-----
nvme1n1 c8:00.0 Speed 8GT/s (ok) Width x2 (downgraded)
1 <nvme1n1>
2 <c8:00.0>
3 <Speed 8GT/s (ok)>
4 <Width x2 (downgraded)>
-----
nvme15n1 48:00.0 Width x2 (downgraded)
1 <nvme15n1>
2 <48:00.0>
3 <>
4 <Width x2 (downgraded)>
-----
nvme25n1 0a:00.0 Speed 32GT/s (ok) Width x2 (downgraded)
1 <nvme25n1>
2 <0a:00.0>
3 <Speed 32GT/s (ok)>
4 <Width x2 (downgraded)>
-----
Run Code Online (Sandbox Code Playgroud)
然后选择要打印的第三个字段的部分就很简单了。例如gensub()像我一样使用。无论任何行中缺少哪些字段,任何字段中有多少单词等,上述内容都将起作用。