次の文字列があります。
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
none65@pci0:2:0:2: class=0x080100 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'interface'
class = base peripheral
subclass = DMA controller
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
"class = Base Peripheral"の前に3行、その後に1行を削除する必要があります。たとえば、次のようになります。
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
私はこれを行うことができませんでした。これはFreeBSDオペレーティングシステムで行われました。
答え1
答え2
この試みawk
:
awk '
FNR==NR && /class[[:blank:]]*=[[:blank:]]*base peripheral/{x=NR; nextfile;}
FNR!=NR && (FNR < x-3 || FNR > x+1)
' file file
file
2回食べますawk
。最初はその行を探します(複数の犬がある場合は最初の行だけが一致します!)。 2番目に省略する行以外の行を印刷します。
コマンド出力とともに使用するには、次のようにします。
awk '...' <(command) <(command)
または
output="$(command)"
awk '...' <(printf '%s' "$output") <(printf '%s' "$output")
答え3
最も簡単な方法は、おそらく次のようになります。すべてのUnixシステムのすべてのシェルでawkを使用することです。
$ cat tst.awk
$0 ~ re {
for (i=(NR-b); i<=(NR+a); i++) {
skip[i]
}
}
{ lines[NR] = $0 }
END {
for (i=1; i<=NR; i++) {
if ( !(i in skip) ) {
print lines[i]
}
}
}
$ awk -v b=3 -v a=1 -v re='class[[:space:]]*=[[:space:]]*base peripheral' -f tst.awk file
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453 device=0xa2d2 subvendor=0x1453 subdevice=0x0008
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453 device=0xa2d2 subvendor=0x1453 subdevice=0x0008
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
入力がシェルに保存されておらず、パイプから出力される場合は、whatever | awk -v ... -f tst.awk
入力をスクリプトに渡すすべてのタスクを実行または実行します。
上記の解決策と同様に、ed
入力全体がメモリに読み込まれますが、入力長が数億行でない場合は問題ありません。これが実際にそうであれば、b
現在の行が正規表現と一致しないときに常に配列の最初の要素を印刷するようにサイズ配列であるスクロールバッファを実装できます。しかし、この場合、書くにはもっと考えが必要で、書くのが難しくなります。重なり合う範囲を処理します。
答え4
問題は、この行の前後にあまりにも多くの行を削除することで説明されていますが、これらの意図された編集の効果は、「プロパティがその値を持つアイテムを削除する」とclass
いうbase peripheral
より高いレベルの意味を持つことは明らかです。
より大きな文書の構造に関連するこのタイプの変換操作に非常に適した言語がある。TxR。
他の人が理解しやすいコードを使用してフィールド抽出を詳細に実行したり、17ヶ月後にあなたが理解できるようにすることができます。
@(repeat)
@addr: class=0x@cl rev=0x@rev hdr=0x@hdr vendor=0x@ven
vendor = '@vendor'
device = '@device'
class = @class
subclass = @subclass
@ (require (nequal class "base peripheral"))
@ (output)
@addr: class=0x@cl rev=0x@rev hdr=0x@hdr vendor=0x@ven
vendor = '@vendor'
device = '@device'
class = @class
subclass = @subclass
@ (end)
@(end)
ランニング:
$ txr data.txr data
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
core1@pci0:2:0:1: class=0x020000 rev=0x00 hdr=0x00 vendor=0x1453
vendor = 'MicSystem'
device = 'controller'
class = network
subclass = ethernet
ここで、パターンマッチングアサーションは@(require expr)
falseの場合、不要なエントリを削除しますexpr
。
フィルタリングを任意に複雑にし、必要に応じて出力形式を簡単に変更できます。内蔵のTXR Lisp言語には魔法のような超能力もあります。