web-dev-qa-db-ja.com

ディレクトリ内のファイル内の最長行を印刷する1行のコマンドはありますか?

たくさんのファイルがあるディレクトリにいるとしましょう。ディレクトリ内のすべてのファイルのコンテンツを検索して、「Cheese」ではなく「ER」という文字列を含む最長の行をどのように表示しますか?

これまでのところ、私の知る限り、これを1行のコマンドで実行しようとしています。

ディレクトリ内のすべてのファイルを検索するために、再帰的にgrep -rを使用する必要があると考えていますが、最終的な目標は最長の行を表示することなので、これまでのところ次のようになっていると思います。

grep -r -e "ER" 

そして、小さな希望から-v "Cheese"を付けた場合、もちろん動作しません。

これは1行のコマンドでは不可能ですか?もしそうなら、私は複数の行で何をする必要がありますか?

4
jkl0619

これがawkソリューションです:

 awk '/ER/ && !/Cheese/ {if (length($0) > maxlen) { maxline=$0; maxlen=length($0);}} END {print maxlen, maxline;}' *

(また、最も長い行の長さも出力しますが、それが必要ない場合は、... END {print maxline;}と発声してください。

Jeremy Doverのgrepソリューションに対する利点は、入力を1回通過することです。欠点は、同じ最大長の行が複数ある場合、最初の行(または> =を使用して長さを比較する場合は最後の行)のみが印刷されることです。 grepソリューションはそれらすべてを出力します。

13
NickD

この1行は、(1つのディレクトリ内のファイルに対して)要求したことを実行します。

awk '{l=length($0)}/ER/&&!/Cheese/&&(length($0)>l){l=length($0);line=$0}END{print(line)}' *

一致する行が複数ある場合、これは、チーズではなくERを含み、以前に選択された行よりも長いfirst行のみを出力します。

また、これは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 {} +
6
Isaac
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というファイルで見つかりました。

6
Kusalananda

私は次のワンライナーが機能するはずだと信じています:

L=`grep -h "ER" * | grep -v Cheese | wc -L`; grep -h "ER" * | grep -v Cheese | grep -P ".{$L}"

最初のコマンドは、「ER」を含むディレクトリ内のファイル内のすべての行を検索し(サブディレクトリがある場合は、-Rオプションのみが必要です。それ以外の場合は、glob *が必要です)、Cheeseを含む行を削除します。 、次にwc -Lコマンドを使用して、これらの行の最も長い行を見つけます。

2番目のコマンド(alas)は、適合行の検索を再度実行しますが、最大長の行を検索します。 grepのバージョンによっては、grepに-Pオプションが必要ない場合があります。

3
Jeremy Dover

文字列の長さを前に付け、数値でソートし、最初の結果の2番目のフィールドを出力して、元の文字列を元に戻すもの。

 grep -h ER * | grep -v Cheese | awk '{ print length($0) " " $0}' | sort -nr| head -1| awk '{print $2}'    

このアプローチにより、必要に応じて「MAX」や「MIN」よりも高度なクエリを実行できます。 AWKの使用に注意してください。これはまさにそれが本当に良いことです。