文字列#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 それらは完全には役に立っていません。
最初の行が#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
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"
に置き換えます。
awk
がnextfile
拡張をサポートしていて、通常以外のファイルを開くことによる潜在的な副作用を気にしない場合:
awk '/^#include/{print substr(FILENAME, 3)}; {nextfile}' ./*
上記では、./
文字を含むファイル名(または=
と呼ばれるファイル)の問題を回避するために、-
接頭辞をFILENAME
で後で削除する を(== --- ==)追加しています 。
zsh
を使用すると、./*
を./*(-.)
に置き換えて、通常のファイル(または上記の[ -f ... ]
アプローチのような通常のファイルへのシンボリックリンク)のみをawk
に渡すことができます。
または、名前の代わりにファイルの内容を印刷するには:
awk 'FNR == 1 {found = /^#include/}; found' ./*
(それはポータブルです)。
for file in *
do
[ -f "$file" ] && head -n 1 < "$file" | grep -q '^#include' && cat < "$file"
done
という事実に注意してください、-q
オプションを有効にすると、grep
はエラーが発生した場合でもゼロのステータスで終了します。
この質問は、bashとsedのソリューションが非常に複雑な完璧な例ですが、(GNU)awkを使用すると、タスクがはるかに簡単になります。
gawk 'FNR==1 && /^#include/{print FILENAME}{nextfile}' *