私
grep -oE '[^ ]+$' pathname
awkまたはsed。誰かが答えて説明できればいいと思います。ありがとうございます。
答え1
awk
はい、スーパーセットなので、以下でもgrep
パターンgrep
を使用できますawk
。
awk '{match($0, "[^ ]+$"); if (RSTART > 0) print substr($0, RSTART, RLENGTH)}'
答え2
grep
まず、コマンドが実行する作業を確認します。
- 行全体ではなく一致する部分だけを出力する
-o
ように指示します。grep
- この
-E
フラグを使用すると、拡張正規表現を使用できます。 '[^ ]+$'
行末で複数回繰り返される空白以外の文字(デフォルトでは行末の単語)と一致します。
テスト実行:
$ cat input.txt
to be or not to be
that is the question
$ grep -oE '[^ ]+$' input.txt
be
question
これで同じことをどのように実行できますかawk
?awk
基本的に、スペースで区切られた項目の各行で動作することを考慮すると簡単ですawk
(単語と呼びます。フィールドと呼びます)。したがって、$NF
awkを使用して印刷できます。NF
フィールド数を含む変数を取得し、特定のフィールドを参照するものとして扱います。ただし、このgrep
コマンドは空でない行にのみ一致します。つまり、そこに少なくとも1つの単語があります。したがって、条件が必要ですawk
。NF
フィールド数がゼロより大きい行でのみ機能します。
awk 'NF{print $NF}' input.txt
GNU awkは少なくとも拡張正規表現をサポートしていることに注意してください。 (私は他の正規表現に精通していないので、他の正規表現については言及しません。) したがって、cuonglmの答えに基づいてバリアントを書くこともできます。
$ awk '{if(match($0,/[^ ]+$/)) print $NF}' input.txt
be
question
GNUでは、sed
拡張正規表現を使用することもできます。これには-r
フラグが必要ですが、単に同じ正規表現を使用することはできません。逆参照が必要です\1
。
$ cat input.txt
to be or not to be
that is the question
blah
$ sed -r -e 's/^.* ([^ ]+)$/\1/' input.txt
be
question
blah
次の基本正規表現を使用して、目的の結果を得ることができます。
$ cat input.txt
to be or not to be
that is the question
blah
$ sed 's/^.* \([^ ].*\)$/\1/' input.txt
be
question
blah
詳しくは、次の投稿をご覧ください。
答え3
まったく:
awk 'NF>0 {print $NF}' ## fails with end of line spaces; \thnaks{cuonglm}
awk '/[^ ]$/ {print $NF}' ## fails with tabs in lasts field; \thanks{Terdon}
awk -F ' +' '$NF {print $NF}' ## too tricky
awk 'match($0,/[^ ]+$/,a){print a[0]}' ## follows def. of grep -o
sedから:
sed -nr 's/(|.* )([^ ]+)$/\2/p'
\ありがとう{cuonglm}
そして(なぜできないのですか?)Perlでは
perl -nlE '/([^ ]+)$/ and say $1'
答え4
これはgrepで実行したいこととsedに対応します。
# there is a space n a tab in the [...]
sed -ne '/[^ ]$/s/.*[ ]//p'
# this makes the code intent visually unambiguous
TAB=`echo 'x' | tr 'x' '\011'`; # tab
SPC=`echo 'x' | tr 'x' '\040'`; # space
h="[$SPC$TAB]"; # whitespace
S="[^$TAB$SPC]"; # nonwhitespace
sed -ne "/$S\$/s/.*$h//p"
sed -ne "s/.*$h\($S$S*\)\$/\1/p"