回答:
そのためにはSedの方が適しています。
ただやる:
sed '/PATTERN/q' FILE
それはこのように動作します:
各行について、一致するかどうかを確認します/PATTERN
。
これは最も効率的なソリューションPATTERN
です。表示されるとすぐに終了するためです。がなければq
、sedはファイルの残りを読み続け、何もしません。大きなファイルの場合、違いが生じる可能性があります。
このトリックは、エミュレートするためにも使用できますhead
。
sed 10q FILE
sed '/PATTERN/Q' FILE
一致した行をスキップします。Q
GNU拡張であるため、どのsedでも動作しません。
sed
grepのほとんどの機能を置き換えることができます。
sed -n '1,/<pattern>/ p' <file>
これは、パターンが一致するまで最初の行から印刷することを意味します。
いくつかの範囲の例
sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
マッチまで印刷します:
awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename
マッチを含めないで最大まで印刷する:
awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
Q
かっこいいが、gnu固有のafaikは、sed -n '/pattern/!p;//q'
より移植性が高いでしょう。
!
ますp
行には適用されないマッチングpattern
が、その後//q
私は...混乱
//
「前の正規表現」を意味する(「空の文字列に一致する」ことを意味すると思った)。同じソリューションの短いバージョンは次のとおりsed -n '/pattern/q;p
です。
次の純粋なGNU grep
メソッドは効率的ではありません。
3つのs を使用して、ファイルbar内のストリング「foo」の最初のインスタンスまでのすべてを検索します。grep
grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar
「foo」の最後のインスタンスまで一致:
grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar
注意:最後の詳細はgrep
:で見つけることができる必要複数行の検索のための正規表現(grepを)。
sed
コードは独自の答えに値するように思われるか、他のコードに追加される可能性があります。7再grep
そこにはなかったので。■ grep
答えは...(プラス、答えは助け表示されない理由。)
上記のMikelの答えに加えて...
を含むすべての行を印刷するには、含むの最初の行FILE
をPATTERN
試してください:
sed '/.*PATTERN.*/{s///;q;}' FILE
これは、パターンを含む行全体に一致し、それを空白行に置き換え、ファイルの残りを処理せずに終了します。
追記:
最後に余分な改行を(別のツールを使用せずに)印刷しないようにするために考えられる最も簡単で明確な方法は、sedを再度実行し、新しい最終行を削除することです。
sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'
...とにかくその行を削除しているので、以前の作業は冗長であり、次のように単純化できます。
sed '/PATTERN/q' FILE | sed '$d'
sed
呼び出しでそれを行う方法を示しています。
tcsh
とbash
エイリアスの両方で使用していたので、私は確認する必要がありました標準とGNU sed
(移植性のため)の両方で機能する比較的簡潔な1行のソリューションがありました。あなたの貢献が非常にうまく満たすかもしれないすべての要件。sed
非常にまれにしか使用しない人として、私の最も重要な要件は、数年後にそれを簡単に編集または再利用したいときにすぐに理解できるものでした。
日常業務で基本的なツールのみを記憶し、エレガントさや効率性の低いソリューションを受け入れたいと考えている人向け:
head -n $(grep -n pattern filename | cut -d: -f1) filename
このコマンドがスクリプト用である場合、よりエレガントな(そしておそらく効率的な)ソリューションを探します。これが1回限りのコマンドまたは使い捨てスクリプトである場合、私は気にしません。
次のいずれかを使用することもできます
tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac
または
tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac
または
tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac
最初のオプションは、OPが提案したものと非常によく似ていますが、ファイル内の行をカウントすることにより、コンテキストの前に十分な行を表示するようにします。
2番目のオプションは、最初の一致の行番号を検索し(内側の「ヘッド」を変更することで変更することもできます)、その番号でヘッドを使用します
最後のオプションは、すべての新しい行を一致で置き換え、2つの隣接する一致を新しい行で置き換えます。これの出力は、2つの一致の間にあるテキストブロックごとの行です。その後、「head」を使用して最初の行(最初の一致までテキストのブロックを必要とする)を選択し、次に各一致を新しい行に再変換します。このオプションは、ファイルが次の形式の場合にのみ機能します
pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern
texttexttext
texttexttexttexttexttexttexttexttext
などなど
sed
下のコマンドはちょっと厄介なので、これらの機能の説明を検討してください。