如何grep一行的缩进行数未知

cer*_*cem 6 grep

我经常需要用它的缩进部分 grep 一行。例如,如果可以知道缩进的行号,我们将通过以下方式实现这一目标:

$ lspci -vq | grep -i wireless -B 1 -A 5

    02:00.0 Network controller: Intel Corporation Wireless 7260 (rev 73)
        Subsystem: Intel Corporation Wireless-N 7260
        Flags: bus master, fast devsel, latency 0, IRQ 64
        Memory at c0600000 (64-bit, non-prefetchable) [size=8K]
        Capabilities: <access denied>
Run Code Online (Sandbox Code Playgroud)

例如,以下命令的输出可能包含也可能不包含所有无线局域网信息:

$ sudo iwlist wlan0 scan | grep -i "cell 13" -A 34
          Cell 13 - Address: 00:1A:2B:93:A7:9C
                    Channel:6
                    Frequency:2.437 GHz (Channel 6)
                    Quality=20/70  Signal level=-90 dBm  
                    Encryption key:on
                    ESSID:"NetMASTER Uydunet-E445"
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s
                    Bit Rates:6 Mb/s; 9 Mb/s; 12 Mb/s; 48 Mb/s
                    Mode:Master
                    Extra:tsf=0000005b923c8227
                    Extra: Last beacon: 4648ms ago
                    IE: Unknown: 00164E65744D415354455220557964756E65742D45343435
                    IE: Unknown: 010882848B962430486C
                    IE: Unknown: 030106
                    IE: Unknown: 050400010000
                    IE: Unknown: 2A0100
                    IE: Unknown: 2F0100
                    IE: Unknown: 32040C121860
                    IE: Unknown: 2D1A2C181BFF00000000000000000000000000000000000000000000
                    IE: Unknown: 3D1606080400000000000000000000000000000000000000
                    IE: Unknown: DD090010180201F00C0000
                    IE: WPA Version 1
                        Group Cipher : CCMP
                        Pairwise Ciphers (1) : CCMP
                        Authentication Suites (1) : PSK
                    IE: Unknown: DD180050F2020101800003A4000027A4000042435E0062322F00
          Cell 14 - Address: 90:F6:52:90:C2:2F
                    Channel:6
                    Frequency:2.437 GHz (Channel 6)
                    Quality=21/70  Signal level=-89 dBm  
                    Encryption key:on
                    ESSID:"selma"
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 6 Mb/s
                              9 Mb/s; 12 Mb/s; 18 Mb/s
Run Code Online (Sandbox Code Playgroud)

如何将此输出裁剪为仅包含一个Cell信息?

编辑

工作脚本维护在https://github.com/ceremcem/sgrep

Joh*_*024 6

基于匹配部分标题的解决方案

要打印开始于Cell 13但停止于之前的文本Cell 14,请使用:

sudo iwlist wlan0 scan | awk '/Cell 13/{f=1} /^ *Cell 14/{f=0} f'
Run Code Online (Sandbox Code Playgroud)

基于监控缩进级别的解决方案

这将打印所有行,以包含Cell 13并继续所有具有更大缩进级别的行开始:

sudo iwlist wlan0 scan | awk '/Cell 13/ && !f{f=1;x=$0;sub(/[^ ].*/,"",x);x=x" ";print;next} f {if (substr($0,1,length(x))==x)print; else f=0}'
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

该代码使用两个变量。 f是一个标志,如果我们在要打印的部分中,则为 1,否则为 0。该字符串x设置为比我们要打印的部分开头的缩进大一个空格。

  • /Cell 13/ && !f{f=1;x=$0;sub(/[^ ].*/,"",x);x=x" ";print;next}

    这将查找包含Cell 13(或任何表示该部分开始的任何内容。如果一行与该匹配并且我们不在该部分中,则:

    1. f 设置为 1。

    2. 该字符串x设置为行首的缩进。

    3. 打印了这一行。

    4. 其余的命令被跳过,我们跳到该next行。

  • f {if (substr($0,1,length(x))==x)print; else f=0}

    如果我们在要打印的部分内(f非零),则检查缩进级别。如果缩进至少为x,则打印此行。否则,通过设置 来表示我们已到达该部分的末尾f=0


vin*_*c17 2

如果要输出 REGEXP 匹配项以及匹配项之后的所有缩进行:

command | perl -ne '/^( *)/; $i = length $1; $j && $i >= $j and print, next; $j = 0; /REGEXP/ and $j = $i + 1, print'
Run Code Online (Sandbox Code Playgroud)

替换REGEXP为您的正则表达式。

例如,

$ perl -ne '/^( *)/; $i = length $1; $j && $i >= $j and print, next; $j = 0; /a/ and $j = $i + 1, print' <<EOF
a
b
  c
  a
    b
    a
    c
      b
    d
  e
    b
  a
    c
e
EOF
Run Code Online (Sandbox Code Playgroud)

输出:

a
  a
    b
    a
    c
      b
    d
  a
    c
Run Code Online (Sandbox Code Playgroud)