awk または sed コマンドは特定の行の正規表現と一致し、成功した場合は true を終了し、そうでない場合は false を終了します。

awk または sed コマンドは特定の行の正規表現と一致し、成功した場合は true を終了し、そうでない場合は false を終了します。

ファイルに次のものが含まれていることを確認する必要があります。特定の行に対する特定の正規表現見つかった場合はtrue(0終了)を返し、それ以外の場合はfalseを返します。私はとても考えていたかもしれませんが、私の試みは少し不器用であることが判明しました。解決策がありますが、考えていない他の解決策を探しています。 Perlを使用することもできますが、人形実行サイクル内で実行されるので、これをできるだけ「軽量」に保ちたいと思います。

この問題は一般的です。 RHEL6では、132で行のコメントを外さない限り、端末の幅を80文字に制限するように画面がパッケージ化されます。このコマンドは、対応する行が変更されたことを確認します。

 awk 'NR==132 && /^#termcapinfo[[:space:]]*xterm Z0=/ {x=1;nextfile} END {exit 1-x}' /etc/screenrc

注:ファイルが132行未満の場合はfalseで終了する必要があります。

ここでは役に立つと思いますsedが、明らかにヌル置換や分岐などの奇妙なトリックを実行する必要があります。それでも学べる sed ソリューションを見たいです。たぶん私が見落としている他のものがあるかもしれません。

編集1:nextfile私のawkソリューションに追加されました

編集2:基準編集3:別のホスト(アイドル)。編集4:各実行を最適化するためにGileのawk時間を誤って使用しました。編集5:新しいベンチ

ベンチマーク

最初の注意:wc -l /etc/screenrcはい216。ラインが存在しない場合は50,000回繰り返し(壁時間で測定):

  • ランダム: 0.545秒
  • 私のオリジナルawkソリューション:58.417
  • 私の編集されたawkソリューション(nextfileを使用):58.364s
  • Gilesのawkソリューション:57.578s
  • 最適化されたPerlソリューション90.352s あや!
  • Sed 132{p;q}|grep -q ...ソリューション:61.259秒
  • Cuonglmのtail | head | grep -q: 70.418s あや!
  • Don_Christie's head -nX |head -n1|grep -q: 116.9s うふ!
  • Terdonのデュアルgrepソリューション:65.127s
  • John1024のsedソリューション:45.764秒

ありがとう、ジョン、ありがとうございます。正直言って、Perlがここに同等であるという事実に驚きました。 Perlは起動時に複数の共有ライブラリをロードしますが、オペレーティングシステムがすべてのライブラリをキャッシュする限り、パーサとバイトエンコーダによって異なります。遠い過去(perl 5.2?)は20%遅いことがわかりました。最初に予想したように、Perlは遅いですが、コピー/貼り付けエラーが原因でPerlが優れているようです。

ベンチマーク2部

実用的な価値がある最大の設定ファイルはです/etc/services。そのため、このファイルのベンチを再実行しましたが、変更する行はファイル全体の3分の2でした。行の総数は1100だったので、7220を選択し、それに応じて正規表現を変更しました(ある場合は失敗し、別の場合は成功するように、ワークベンチでは常に失敗します)。

  • Johnのsedソリューション:121.4s
  • Christieの{head;head}|grepソリューション:138.341s
  • Kangamのtail|head|grepソリューション:77.948秒
  • 私のawkソリューション:175.5s

答え1

GNU sedの使用:

sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}; $q1'

どのように動作しますか?

  • 132 {/^#termcapinfo[[:space:]]*xterm Z0=/q}

    132行目で正規表現を確認してください^#termcapinfo[[:space:]]*xterm Z0=。出口が見つかった場合、デフォルトのq出口コードは 0 です。ファイルの残りの部分はスキップされます。

  • $q1

    最後の行に達すると、$終了コード1:を使用して終了しますq1

効率

ファイルの 132 行目を読み取る必要がないため、このバージョンは 132 行目またはファイルの末尾に到達すると、最初に発生するとすぐに終了します。

sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q; q1}; $q1'

空のファイル処理

上記のバージョンは空のファイルに対してtrueを返します。ファイルが空の場合、コマンドは実行されず、sedがデフォルトの終了コード0で終了するためです。このような状況を回避するには、次の手順を実行します。

! sed -n '132 {/^#termcapinfo[[:space:]]*xterm Z0=/q1; q}'

ここで、sedコマンドは、必要な文字列が見つからない限りコード0で終了し、その文字列が見つかった場合はコード1で終了します。前述の!内容はシェルにこのコードを裏返し、必要なコードに戻るように指示します。!すべてのPOSIXシェルはこの修飾子をサポートしています。このバージョンは空のファイルでも機能します。 (帽子チップ:G-Man)

答え2

POSIXツールボックスの使用:

tail -n +132 </etc/screenrc | head -n 1 | grep -q pattern

答え3

awkでこれをより効率的に実行できます。関連する行に達したら終了します。

awk 'NR==132 {if (/^#termcapinfo[[:space:]]*xterm Z0=/) found=1; exit}
     END {exit !found}' /etc/screenrc

またはできますGNU sedの使用(ただし、ポータブルsedでは終了コードを指定することはできません。)

あるいは、ツールを一緒にグループ化するUnix哲学を使用することもできます。つまり、head目的の行を使用して抽出してtailに渡しますgrep

</etc/screenrc tail -n +132 | head -n 1 |
grep -q '^#termcapinfo[[:space:]]*xterm Z0='

または、sedを使用して必要な行を抽出できます。

</etc/screenrc sed -n '32 {p; q;}' |
grep -q '^#termcapinfo[[:space:]]*xterm Z0='

(これらの両方は、空行と短すぎるファイルで同じ結果が欲しいという事実に依存します。)

headこれらの小さなファイルの場合、最速の方法は単一のツールを使用することです。複数のプログラムを実行するオーバーヘッドは、専用ツール(たとえば、および)を使用してtail取得できるパフォーマンスの向上よりも大きいためですsed。行132000000が必要な場合は、それから始めるのがtail -n +132000000おそらく他のものよりも速いでしょう。

答え4

perl.

次のことができます。

#!/usr/bin/env perl

use strict;
use warnings;

open ( my $input_fh, '<', "/etc/screenrc" ) or die $!; 
while ( <$input_fh> ) {
   if ( $. == 132 
   and m/^#termcapinfo[[:space:]]*xterm Z0=/ ) {
       exit 0; 
   }
}

exit 1;

ライナーで圧縮できます。

perl -ne 'exit 0 if $. == 132 and  m/^#termcapinfo[[:space:]]*xterm Z0=/ END { exit 1 }' 

関連情報