複数のパターンを使用するファイルを探したいです。
これは私の元のコマンドです。しかし、入力は非常に長くてxargs zgrep
冗長です。入力するパターンが10個以上の場合はどうなりますか?
find -mtime -$a -type f ! -name "*.bak*" | xargs zgrep -il "$b" | xargs zgrep -il "$c" | xargs zgrep -il "$d" | xargs zgrep -il 'ST.997' | sort -u
たとえば、次のように少ない文字を入力したいとします。
find -mtime -$a -type f ! -name "*.bak*" | xargs zgrep -il "$b && $c && $d" | sort -u
編集する:これらのパターンは$
。これは、コマンドがスクリプト内にあり、これらの変数に文字列/数値があるためです。
私はこれを使ってスクリプト、特にランタイムを改善します。
ベストアンサー1
各モードでファイルの圧縮を解凍しないようにするには、次のようにします。
PATTERNS='foo
bar
baz' find . -mtime -"$a" -type f ! -name "*.bak*" -exec awk -v q=\' '
function shquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(ENVIRON["PATTERNS"], pats, "\n")
for (arg = 1; arg < ARGC; arg++) {
file = ARGV[arg]
cmd = "gzip -dcf < " shquote(file)
for (i = 1; i <= n; i++) notfound[pats[i]]
left = n
while (left && (cmd | getline line) > 0) {
for (pat in notfound) {
if (line ~ pat) {
if (!--left) {
print file
break
}
delete notfound[pat]
}
}
}
close(cmd)
}
exit
}' {} +
スキーマは次のように処理されます。awk
grep -E
/supported 拡張正規表現に似たパターンですegrep
。大文字と小文字を区別しない一致のために、-v IGNORECASE=1
GNUを使用してifを追加しawk
たり、次のように移植可能に変更したりできます。
PATTERNS='foo
bar
baz' find . -mtime -"$a" -type f ! -name "*.bak*" -exec awk -v q=\' '
function shquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split(tolower(ENVIRON["PATTERNS"]), pats, "\n")
for (arg = 1; arg < ARGC; arg++) {
file = ARGV[arg]
cmd = "gzip -dcf < " shquote(file)
for (i = 1; i <= n; i++) notfound[pats[i]]
left = n
while (left && (cmd | getline line) > 0) {
line = tolower(line)
for (pat in notfound) {
if (line ~ pat) {
if (!--left) {
print file
break
}
delete notfound[pat]
}
}
}
close(cmd)
}
exit
}' {} +
(スキーマに非標準のERE拡張がないと仮定すると(たとえば)\S
に変換されます\s
。
このawk
コマンドをzgrep-many
スクリプトに入れて使いやすくすることができます。それは次のとおりです。
#! /bin/sh -
usage() {
cat >&2 << EOF
Usage: $0 [-e <pattern>] [-f <file] [-i] [pattern] files
List the files for which all the given patterns are matched.
EOF
exit 1
}
ignorecase=
PATTERNS=
export PATTERNS
NL='
'
sep=
while getopts e:f:i opt; do
case $opt in
(e) PATTERNS=$PATTERNS$sep$OPTARG; sep=$NL;;
(f) PATTERNS=$PATTERNS$sep$(cat < "$OPTARG") || exit; sep=$NL;;
(i) ignorecase='tolower(';;
(*) usage;;
esac
done
shift "$((OPTIND - 1))"
if [ -z "$PATTERNS" ]; then
[ "$#" -gt 0 ] || usage
PATTERN=$1; shift
fi
[ "$#" -eq 0 ] && exit
exec awk -v q=\' '
function shquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
BEGIN {
n = split('"$ignorecase"'ENVIRON["PATTERNS"]'"${ignorecase:+)}"', pats, "\n")
for (arg = 1; arg < ARGC; arg++) {
file = ARGV[arg]
cmd = "gzip -dcf < " shquote(file)
for (i = 1; i <= n; i++) notfound[pats[i]]
left = n
while (left && (cmd | getline line) > 0) {
'"${ignorecase:+line = tolower(line)}"'
for (pat in notfound) {
if (line ~ pat) {
if (!--left) {
print file
break
}
delete notfound[pat]
}
}
}
close(cmd)
}
exit
}' "$@"
次のように使用されます。
find ... -exec zgrep-many -ie foo -e bar -e baz {} +
例えば。