web-dev-qa-db-ja.com

ファイルの最初の行に特定の文字列が含まれているかどうかを確認する方法

文字列#includeで始まるディレクトリ内のすべてのファイルを検索して印刷するシェルスクリプトを作成する必要があります。今、私は文字列がファイルにあるかどうかを確認する方法を知っています:

for f in `ls`; do
    if grep -q 'MyString' $f; then:
        #DO SOMETHING
    fi

しかし、これを最初の行にどのように適用できますか?最初の行の変数を作成して、それが#includeで始まるかどうかを確認することを考えていましたが、これを行う方法がわかりません。 readコマンドを試しましたが、変数に読み込めませんでした。

この問題に対する他のアプローチを聞きたいのですが。多分おかしい?とにかく、最初の行が#includeで始まるかどうかを確認する必要があります。その文字列が含まれているかどうかではありません。それが私がそれらの質問を見つけた理由です: 最初の行が特定のパターンに一致する場合にのみファイルの内容を印刷する方法?https://stackoverflow.com/questions/5536018/how-to-print -matched-regex-pattern-using-awk それらは完全には役に立っていません。

6
Z E Nir

最初の行が#includeで始まるかどうかを簡単に確認できます(GNUおよびAT&T)sed:

sed -n '1{/^#include/p};q'   file

または簡略化(およびPOSIX互換):

sed -n '/^#include/p;q'   file

ファイルの最初の行に#includeが含まれている場合にのみ出力されます。チェックを行うには、最初の行を読み取るだけで十分なので、非常に高速になります。

したがって、(sedを使用した)すべてのファイルのシェルループは次のようになります。

for file in *
do
    [ "$(sed -n '/^#include/p;q' "$file")" ] && printf '%s\n' "$file"
done

If pwdには(ディレクトリではなく)ファイルのみがあります。

ファイルのすべての行を印刷する必要がある場合、投稿された最初のコードと同様の解決策が機能します(GNUおよびAT&Tバージョン)。

sed -n '1{/^#include/!q};p'  file

または、(BSD互換のPOSIXfiedバージョン):

sed -ne '1{/^#include/!q;}' -e p  file

または:

sed -n '1{
           /^#include/!q
         }
         p
       '  file
10
Isaac
for file in *; do
  [ -f "$file" ] || continue
  IFS= read -r line < "$file" || [ -n "$line" ] || continue
  case $line in
    ("#include"*) printf '%s\n' "$file"
  esac
done

名前ではなくファイルの内容を出力するには、printfコマンドをcat < "$file"に置き換えます。

awknextfile拡張をサポートしていて、通常以外のファイルを開くことによる潜在的な副作用を気にしない場合:

awk '/^#include/{print substr(FILENAME, 3)}; {nextfile}' ./*

上記では、./文字を含むファイル名(または=と呼ばれるファイル)の問題を回避するために、-接頭辞をFILENAMEで後で削除する を(== --- ==)追加しています

zshを使用すると、./*./*(-.)に置き換えて、通常のファイル(または上記の[ -f ... ]アプローチのような通常のファイルへのシンボリックリンク)のみをawkに渡すことができます。

または、名前の代わりにファイルの内容を印刷するには:

awk 'FNR == 1 {found = /^#include/}; found' ./*

(それはポータブルです)。

5
for file in *
do
  [ -f "$file" ] && head -n 1 < "$file" | grep -q '^#include' && cat < "$file"
done

という事実に注意してください、-qオプションを有効にすると、grepはエラーが発生した場合でもゼロのステータスで終了します。

2
francescop21

この質問は、bashとsedのソリューションが非常に複雑な完璧な例ですが、(GNU)awkを使用すると、タスクがはるかに簡単になります。

gawk 'FNR==1 && /^#include/{print FILENAME}{nextfile}' *
0
user000001