web-dev-qa-db-ja.com

安全なフォールバックとしてgrep / sedする方法

Grepアクションをネストする方法を探しているので、最初のgrepが一致しない場合、入力に対して以下が使用されますが、一部のgrepが正常に終了すると、チェーンが中断されます

echo $'b\nc\nd' | { grep 'a' || grep 'b' || grep 'c' || grep 'd'; }で試してみましたが、最初のgrepが失敗し、成功して2番目のgrepが終了することを期待していたため、グローバル出力は「b」になります。

次に、grepにフラグを立てて、何にも一致しない場合に入力をそのまま出力するようにすると、もっと簡単な方法があるのではないかと思いました。それならこれは同じくらい簡単でしょう

echo $'b\nc\nd' | grep --if-error-print-input 'a' | grep --if-error-print-input 'b' | grep --if-error-print-input 'c' | grep --if-error-print-input 'd'

入力と出力の例

echo $'Foo\nBar' | grep -e 'Bar' -e 'Foo' | head -n 1
Foo

Barが優先されるので期待します

1
Whimusical

必要なことは、awkのみで実行できますが、sedまたは単一のgrepでは実行できません。

$ cat regexes 
c
b
a

最初に一致する行は、パターンごとに保存する必要があります(最高ランクの一致よりも優先順位が低いものを除く)。

echo $'b\nc\nd' |
    awk 'BEGIN { while (getline regex <"regexes") regexes[i++]=regex; num=i; limit=i; };'\
      '{ for(i=0;i<limit;i++) { if($0~regexes[i]) { regexmatch[i]=$0; limit=i; if (i==0) { exit; } else break; }; }; };'\
      'END { for(i=0;i<num;i++) if (regexmatch[i]!="") { print regexmatch[i]; exit; }; }'
c
1
Hauke Laging