grepコマンドにマッチした部分から指定行を表示する機能があります.
例えば以下の例ではマッチした部分から後ろ11行を表示.
$ man grep | grep 'Context Line Control' -A 11 Context Line Control -A NUM, --after-context=NUM Print NUM lines of trailing context after matching lines. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or --only-matching option, this has no effect and a warning is given. -B NUM, --before-context=NUM Print NUM lines of leading context before matching lines. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or --only-matching option, this has no effect and a warning is given. -C NUM, -NUM, --context=NUM Print NUM lines of output context. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or --only-matching option, this has no effect and a warning is given.
マッチした部分以降全てを表示したいことがあります.行数を確認するのが面倒だったりするので -A 999
とかやりがちです.
ugrep に最後まで表示できるオプションがあるのに気づいたのでメモしておきます.
DebianではGNU grepは grep
パッケージで,ugrep は ugrep
パッケージで提供されています.
導入
$ sudo apt install grep $ sudo apt install ugrep
GNU grep を試す
適当なテキスト
$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head root daemon bin sys sync games man lp mail news
GNU grep
で man
の後2行を表示$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | grep -A2 -- ^man$ man lp mail
GNU grep
で man
の前2行を表示$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | grep -B2 -- ^man$ sync games man
GNU grep
で man
の前後それぞれ2行を表示$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | grep -C2 -- ^man$ sync games man lp mail
GNU grep
で man
の前1行後2行を表示$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | grep -B1 -A2 -- ^man$ games man lp mail
GNU grep
で man
の後99行を表示(実際はそんなに行数がないので最後まで表示)$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | grep -A99 -- ^man$ man lp mail news
ugrep を試す
ugrep もGNU grepと同じように -A/-B/-C
が使えます.そして -A
利用時には行数に -1
が指定可能でこれでマッチ部分から最後まで表示できます.
grep
で man
の後すべてを表示$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | ugrep -A-1 -- ^man$ man lp mail news
-B
には使えない$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | ugrep -B-1 -- ^man$ ugrep: warning: exception while searching (standard input): Inappropriate ioctl for device
tacで逆順にして
-1
で切り取ったと再度tacで逆順に$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | tac | ugrep -A-1 -- ^man$ | tac root daemon bin sys sync games man
ugrepは他にも対話型問い合わせの機能(-Q)やインデックスを作成して検索を高速化(-indexer)する機能など様々な機能が含まれています.
もっと使いこなしていきたいところです.
別解: sed, awk, perl
sed
$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | sed -n '/^man$/,$p' man lp mail news
awk
$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | awk '/^man$/',0 man lp mail news
perl
$ awk -F: '{if ($3 < 1000) {print $1 }}' /etc/passwd | head | perl -ne "print if /^man$/ .. eof;" man lp mail news
環境
$ dpkg-query -W grep ugrep sed gawk perl gawk 1:5.3.2-1 grep 3.11-4 perl 5.40.1-3 sed 4.9-2 ugrep 7.4.2+dfsg-1 $ lsb_release -dr Description: Debian GNU/Linux 13 (trixie) Release: 13 $ arch x86_64