私はファイルが多くのディレクトリにあるとしましょう。ディレクトリ内のすべてのファイルの内容を検索し、「ER」文字列を含めるが「Cheese」は含まない最も長い行を表示するにはどうすればよいですか?
私が知っている限り、私は1行のコマンドでこれをやろうとしています。
ディレクトリ内のすべてのファイルを検索するには、grep -rを繰り返し使用する必要があると思います。
grep -r -e "ER"
小さな希望で-v "cheese"を追加すると、もちろん動作しません。
1行のコマンドでこれは可能ではありませんか?それでは、複数行で何をすべきですか?
答え1
以下はawkソリューションです。
awk '/ER/ && !/Cheese/ {if (length($0) > maxlen) { maxline=$0; maxlen=length($0);}} END {print maxlen, maxline;}' *
(最も長い行の長さも出力しますが、そうしたくない場合はただ... END {print maxline;}
。
Jeremy Doverのgrepソリューションに比べて利点は、入力を一度だけ渡すことです。欠点は、最大長が同じ複数行がある場合は最初の行だけが印刷されることです(または、長さを比較するために> =を使用する場合は最後の行)。 grepソリューションはすべての行を印刷します。
答え2
この行は目的の操作を実行します(ディレクトリ内のファイルについて)。
awk '{l=length($0)}/ER/&&!/Cheese/&&(length($0)>l){l=length($0);line=$0}END{print(line)}' *
複数行が一致する場合のみ印刷最初ER(チーズではない)を含み、以前に選択した行よりも長い行です。
また、pwd(*) のファイルを調べます。再帰が必要な場合は、findコマンドを使用してファイルを選択する必要があります。
find . -type f -iname '*.sh' -exec sh -c 'awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'' "$@"' awksh {} +
または複数行で書く(読みやすくするために):
find . -type f -iname '*.sh' -exec sh -c '\
awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'\
' "$@"' awksh {} +
答え3
awk '/ER/ && !/Cheese/ && length > m {
m=length; d=$0; f=substr(FILENAME, 3); n=FNR
}
END { print m, f ":" n, d }' ./*
現在のディレクトリに通常のファイルしかないと仮定すると、m
質問()の条件を満たす最も長い行の長さと、ファイル名(f
)、行番号(n
)、およびd
ファイルを含む行自体()が印刷されます。発見。
出力は次のとおりです。
8 file:3 Hello ER
最も長い行は8文字で、ファイル名の3行目にありますfile
。
答え4
前に文字列の長さを加えて数値でソートし、最初の結果の2番目のフィールドを印刷して元の文字列を取得します。
grep -h ER * | grep -v Cheese | awk '{ print length($0) " " $0}' | sort -nr| head -1| awk '{print $2}'
この方法では、必要に応じて「MAX」または「MIN」よりも複雑なクエリを実行できます。 AWKの使用に注意してください。それが本当の利点です。