web-dev-qa-db-ja.com

Grep行ですが、最初の行を通過させます

dfからの次の出力を検討してください。

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        23G  6.1G   16G  29% /
udev             10M     0   10M   0% /dev
tmpfs           397M  420K  397M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           1.8G  904K  1.8G   1% /run/shm
/dev/sda6       890G  324G  521G  39% /home
/dev/sdb1       459G  267G  169G  62% /home/user/mnt
none            4.0K     0  4.0K   0% /sys/fs/cgroup

"/dev"で始まる行のみを表示し、見出しは保持し、その他はすべて除外するにはどうすればよいですか。一時ファイルや変数を使用することに頼る必要がないようにもしたいですか?注:見出しはロケールに依存するため、正規表現では見出しをキャッチできません。

26
Ernest A

単純なgrepよりも少し洗練されたアプローチを使用します。

  1. awk

    df -h | awk 'NR==1 || /^\/dev/'
    

    NRは現在の行番号なので、これが最初の行である場合は上記のawkスクリプトレットが出力されますまたは現在の行は/devで始まります。これを投稿した後、@ 1_CRの回答と同じであることがわかります。しかたがない...

  2. Perl

    df -h | Perl -ne 'print if (/^\/dev/ || $.==1)'
    

    同じ考え方ですが、Perlでは特殊変数$.が現在の行番号です。別の方法は

    df -h | Perl -pe '$_="" unless /^\/dev/ || $.==1'
    

    -pスイッチは、入力ファイルのすべての行を出力します。現在の行の値は$_に保持されるため、現在の行が必要でない限り、$_を空に設定します。

  3. sed

    df -h | sed -n '1p; /^\/dev/p'
    

    -nは、通常の出力を抑制して、行が出力されないようにします。 1pは最初の行を印刷することを意味し、/^\/dev/p/devで始まる行を印刷することを意味します。

    以下のコメントで指摘されているように、現在のシステムのロケールによってヘッダー行が/devで始まるというまれなケースでは、上記のコマンドで2回出力されます。 Stephane Chazelas 指摘 これには問題がないこと:

    df -h | sed  -e 1b -e '/^\/dev/!d'
    
  4. grep

    df -h | grep -E '^(/dev|File)'
    

    これは、あなたが言ったようにLOCALEの問題のために移植できないかもしれません。ただし、ロケールまたはdfバージョンが最初の行にパスを与えないことは合理的に確実であるため、/を含まない行の検索も機能するはずです。

    df -h | grep -E '^[^/]*$|^/dev'
    
38
terdon

df出力を解析しようとして問題が発生します ですが、単純なケースでは、次のように機能する可能性があります

LC_ALL=C df -P | awk 'NR == 1 || /^\/dev/' 
15
iruvar

これも機能するはずです(ただし、テストされていません)。

df | (read a; echo "$a"; grep /dev)

または

df | (head -n 1; grep ^/dev)
11
daniel kullmann
df -h | tee >(head -1) >(sleep 0.5;grep ^/dev) > /dev/null;sleep 1.0
5
Robert Jacobs
df | head -n 1; df | grep ^/dev
3
ohlemacher
df | grep -n '' | grep -E '^1:|[^:]*:/dev' | sed 's/[^:]*://'

grep -nストリームに行番号を挿入します。次に、egrepを介して最初の行と対象の行を引き出し、sedを介して出力から追加した番号を削除します。

positive lookbehinds を使用することでsedを回避できます(これはgrep[〜#〜] pcre [〜#〜]で処理できる =エンジン(-P))および-oは、一致したパターンのみを出力するようにgrepに指示します。

df | grep -n '' | grep -Po '(?<=^1:)(.*)|(?<=:)(/dev.*)'
3
Chaim Geretz

bodyの定義を sortから取得しますが、ヘッダー行を先頭に保持します

# print the header (the first line of input)
# and then run the specified command on the body (the rest of the input)
# use it in a pipeline, e.g. ps | body grep somepattern
body() {
    IFS= read -r header
    printf '%s\n' "$header"
    "$@"
}

このように使う

$ df -h | body grep ^/dev
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        23G  6.1G   16G  29% /
/dev/sda6       890G  324G  521G  39% /home
/dev/sdb1       459G  267G  169G  62% /home/user/mnt
2
Mikel

Df出力をフィルタリングする代わりに、その入力をフィルタリングできます。

前:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
C:/Cygwin/bin   150G   76G   74G  51% /usr/bin
C:/Cygwin/lib   150G   76G   74G  51% /usr/lib
C:/Cygwin       150G   76G   74G  51% /
C:              150G   76G   74G  51% /cygdrive/c

後:

$ mount | grep ^C:/Cygwin | cut -d' ' -f3 | xargs df -h
Filesystem      Size  Used Avail Use% Mounted on
C:/Cygwin/bin   150G   76G   74G  51% /usr/bin
C:/Cygwin/lib   150G   76G   74G  51% /usr/lib
C:/Cygwin       150G   76G   74G  51% /

PDATE 2014-01-24 08:03 UTC:行頭のC:/ Cygwinのgrepのみ

2
mkalkov