<p>对于GNU <code>awk</code>:</p>
<pre><code>gawk -F'\n' -v RS='Device \\\\\\\\.\\\\' '
NF > 2 { # ignore the extraneous very first line
delete dict # delete dictionary from previous record
dict["Device"] = $1 # store device name
for (i=2;i<NF;++i) { # store other fields in dict.
split($i, tkns, / = /) # split into field name (e.g., "Desc") and value
# clean up strings (remove leading spaces from field name, remove
# double quotes from value, and store in dictionary.
dict[gensub(/^ +/, "", "", tkns[1])] = gensub(/"/, "", "g", tkns[2])
}
# Output desired fields, using the dictionary.
printf "%s - %s - %s - %s\n", dict["Device"], dict["Desc"], dict["Mode"], dict["Flags"]
}
' file
</code></pre>
<p>基本方法:</p>
<ul>
<li>将输入拆分为记录,每个记录包含与给定显示相关的所有行:<code>-v RS='Device \\\\\\\\.\\\\'</code>(请注意,输入中的每个文字<code>\</code>必须用<em>3</em><code>\</code>转义)。这将设置特殊变量<code>RS</code>,即输入记录分隔符,它告诉<code>awk</code>如何根据指定的正则表达式将输入拆分为记录。(<code>$0</code>然后引用正在处理的整个当前记录。)</li>
<li>每条记录按行(<code>-F'\n'</code>)-<code>-F</code>设置特殊变量<code>FS</code>,即输入字段分隔符,它告诉<code>awk</code>如何将每条记录拆分为单独的字段(<code>$1</code>,<code>$2</code>,…)</li>
<li>然后建立一个字段值字典,这样就可以通过字段名来引用值,例如<code>dict["Desc"]</code>-请参阅源代码中的注释。你知道吗</li>
<li>最后,一个<code>printf</code>语句从感兴趣的字段值合成所需的输出字符串。你知道吗</li>
</ul>
<p>注意:使用了以下特定于GNU的非POSIX特性:</p>
<ul>
<li>不仅仅是单个字符的<code>RS</code>值</li>
<li>用于灵活的、基于regex的字符串替换的<code>gensub()</code>函数(比POSIX <code>sub</code>/<code>gsub</code>函数更灵活)</li>
<li>使用<code>delete</code>语句删除整个<em>数组。你知道吗</li>
</ul>