最初の行が特定のパターンに一致する場合にのみファイルの内容を印刷する方法は?


11

スクリプトを作成しています。ファイルの最初の行が特定のパターンに一致するかどうかを確認し、一致する場合はファイルを出力します。どうすればこれを達成できますか?

パターンを確認するにはどうすればよいですか?パターンをチェックし、出力に基づいて何かを行う方法はありますか?

編集:この質問を見てください:https : //stackoverflow.com/questions/5536018/how-to-get-match-regex-pattern-using-awk-from-file

このようなものが欲しいのですが、どれもうまくいきませんでした。基本的に、最初の行が正規表現パターンと一致するかどうかを確認し、それに基づいてファイルの行を出力します。


1
あなたが期待している出力は何ですか?あなたが探しているパターンは何ですか?これまでに何を試しましたか?
tachomi

編集された@tachomiをご覧ください
Mathew

回答:


17

あなたはそれを行うことができますed

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

ここでの秘訣はPATTERN1stオンラインでそれ自体を置き換えようとすることです。ed指定されたパターンが見つからない場合はエラーになりますので、,p(ファイル全体を印刷)1s/PATTERN/&/は成功した場合にのみ実行されます。

またはsed

sed -n '1{
/PATTERN/!q
}
p' infile

これqは、最初の行が!一致しない場合()に一致しPATTERN、そうでない場合はpすべての行がリントされます。
または、Toby SpeightがGNUで指摘したようにsed

sed '1{/PATTERN/!Q}' infile

Qと同じですqが、パターンスペースは印刷されません。


あなたは可能性Qの代わりにqGNUのためには、sedの、またはdq(ポータブル)それほど必要としないように-nフラグやp:コマンドをsed '1{/PATTERN/!Q}' infileまたはsed -e '1{' -e '/PATTERN/!{' -e 'd' -e 'q' -e '}' -e '}' infileそれぞれ。
Toby Speight

dコマンドサイクルを再開します。:-|
Toby Speight 2015

GNUを使用sedすると、最初のsedコマンドはsed: -e expression #1, char 10: extra characters after command()のために文句を言いますpが、ed最後のsed提案はうまくいきます。
Skippy le Grand Gourou 2017

注意:この回答で提供されるソリューションには、他の回答よりもパイプに適用できるというメリットがあります。
Skippy le Grand Gourou 2017

1
@SkippyleGrandGourou-コマンドをセミコロンで区切らずに1行に変換しようとしました-これが適切な方法ですsed -n '1{/PATTERN/!q};p'
don_crissti

15

POSIXツールチェストの場合:

{ head -n 1 | grep pattern && cat; } <file

1
{ダブル} <甘い。
mikeserv 2015

@mikeserv:新しい人が混乱するのを防ぐために使用するつもりですが、編集されたStephaneはより明確です。
cuonglm

8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

txt、現在のディレクトリにある非表示でないファイルの名前を出力します。その最初の行は、拡張正規表現patternをサポートするawk実装と一致しnextfileます。

ファイル名を印刷する代わりに、ファイルの内容全体を印刷したい場合は、次のようにします。

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

これは1つのコマンドのみを実行するという点でawk効率的ですが、ファイルの内容をダンプするための最も効率的なコマンドではなく、大きなファイルの場合、次のようなことを行うことでパフォーマンスを向上させることができます。

 awk '/pattern/{printf "%s\0", FILENAME}; {nextfile}' ./*.txt |
   xargs -r0 cat

つまりawk、一致する(0区切り)ファイルのリストを印刷し、catその内容のダンプに依存する場合にのみ使用します。


6

シェルスクリプトを作成している場合は、次のようにすることができます。

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

または、Perlでは:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*

@StéphaneChazelas:多分close ARGV、に割り当てるよりもイディオムが多いかもしれません$.
cuonglm

@terdon Yoursはコードゴルフのように見えます。すべて1行で、変数名の前後に角括弧はなく、クリーンな構造を推奨していません。そして私が投稿したときにあなたはドル記号が欠けていました、それは単にbashを教える方法ではありません。これらの要素はあなたが持っているように見えるperlの背景にあると思いますので、あなたは許されるでしょう!;)

@guestこんにちは、サイトへようこそ!回答は実際の質問に回答している場合にのみ投稿する必要があるため、回答をコメントに変換しました。これは古典的な意味でのフォーラムではなく、ここでは純粋なQ&Aのみが必要です。ヘルプセンターをご覧になるか、サイトをよく理解するためにツアーに参加することをお勧めします。とはいえ、私の背景は実際には生物学にあるので、はい、私のコードはきれいではありません。ブラケットが保護するこれを壊すものは何ですか?
terdon

@ゲストああ、申し訳ありませんが、コメントできないことを忘れていました。気軽にチャットで説明してください。何かを学ぶことができると思います。
terdon

5

オールドスクール、あなたの文章を標準的なコマンドに翻訳してください:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

bashを学ぶための良いスタートです。簡単な解決策が必要な場合は、sed-、awk-、またはperl-answersを試してください。どちらもすばらしいですが、学習するために必要な(おそらく必要な)独自の言語です。

これは非常に単純な例なので、詳細を知りたい場合は、ruby、php、js(nodejsなど)、またはファイルアクセスを許可するその他の言語でも同じことを試すことができます。C / C ++やJavaでも、小さなタスクで簡単に管理できるはずです。


1
これは、の代わりに使用することを除いて、基本的にはのものと同じif/elseです[ ] &&
terdon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.