0

次の AWK スクリプトを書き留めて、フル パスに少なくとも 2 つの「a」文字が含まれ、「u」文字が含まれていないファイルを一覧表示しました。

BEGIN {}

{
if ( (match($1, "^.*[a].*[a]+$") ) )
print $1
}

END{}

現時点では、スクリプトで「u」文字を削除することはできません。必要なものを取得するには、どのような変更を行う必要がありますか?

PS次のコマンドを使用して、個別に作成された「data」と呼ばれるファイルから、ファイル名をフルパスで読み取ります。

find / -name '*' > data
4

3 に答える 3

4

bashを使用しているので、sed、awk、findなどの外部ツールなしでこれを行うことができます。

#!/bin/bash

shopt -s globstar

for filename in **/*a*a*; do
  [[ "$filename" =~ u ]] || echo "$filename"
done 

これが絶対に厄介である必要がある場合、私は使用します:

awk '/a.*a/ && ! /u/' data

アップデート:

gniourf_gniourfの丁寧な警告に従って、正規表現の代わりにパス名展開(globs)を使用するとパフォーマンスが向上する場合があります。これが(非科学的な)ベンチマークです:

$ rm -f file
$ for (( i=1000000; i-- ; )); do echo u >> file; done
$ time bash -c 'while read i; do [[ $i = *u* ]]; done < file'

real    0m8.291s
user    0m6.570s
sys     0m1.717s
$ time bash -c 'while read i; do [[ $i =~ u ]]; done < file'

real    0m10.416s
user    0m8.676s
sys     0m1.735s

「ユーザー」行は、私たちが関心を持っている行です。

これにより、fileglobが正規表現よりも約30%速く実行されているように見え、100万件のレコードをテストして肯定的な結果が得られます。

奇妙なことに、テストが失敗してもそれほど改善はありません。

$ time bash -c 'while read i; do [[ $i = *a* ]]; done < file'

real    0m8.244s
user    0m6.601s
sys     0m1.639s
$ time bash -c 'while read i; do [[ $i =~ a ]]; done < file'

real    0m9.757s
user    0m8.121s
sys     0m1.630s

これは、これらの100万回のテストで23%の速度向上にすぎません。この種のシェルスクリプトの最適化が重要な場合(何百万ものテストを実行していて、CPUサイクルに余裕があるとは思わないため)、コースがawkからbashに移行するときに、gniourf_gniourfの提案を検討してください。

于 2012-12-16T14:07:02.613 に答える
3

「フルパスに少なくとも2つの「a」文字があり、「u」文字がないファイルをリストしてください」:

find / -type f -path "*a*a*" ! -path "*u*" > data
于 2012-12-16T13:59:43.583 に答える
3

dataファイルを完全に回避するために、このタスクの検索オプションを直接使用するのはどうですか?

find / -name '*a*a*' -not -name '*u*'

さて、本当にファイルが必要な場合はdata、asedで十分です。

sed -n '/a.*a/{/u/!p}' data

本当に使いたいならawk

awk '/a.*a/ { if ($LINE !~ /u/) print ; }' data

そして、純粋なbashバージョンの場合:

while read -r file; do
    if [[ "$file" = *a*a* ]] && [[ "$file" != *u* ]]; then 
        echo "$file"
    fi
done < data

dataそして、グロブを使用して、ファイルがまったくなく、findコマンドがない純粋なbashバージョンの場合:

#!/bin/bash

shopt -s globstar
shopt -s nullglob

for file in /**/*a*a*; do
    if [[ "$file" != *u* ]]; then
        echo "$file"
    fi
done

この最後のバージョンは、ファイルがたくさんある場合、他のバージョンよりもはるかに遅くなります(これは一般的にの場合です/)。すべてのファイル名を丸呑みしてからエコーします。findファイル名が見つかったときにエコー(および/または処理)されるため、を使用したソリューションが最適です。

お役に立てれば!

于 2012-12-16T14:00:40.800 に答える