小さなスクリプトがあります。
#!/bin/bash
# test for regular expressions to match...
DIR="/search/path/"
NAME="FOO[0-9][0-9]_<bar|dog|cat>"
for FILE in `find ${DIR} -maxdepth 1 -type f -name "*\.[dD][oO][cC]"`
do
BASENAME=`basename ${FILE}`
FILENAME="${BASENAME%.*}"
if [[ "${FILENAME}" == ${NAME} ]]
then
echo "Found $FILENAME"
else
echo "$FILENAME not matching..!"
fi
done
このスクリプトでは、FOO[0-9[0-9]_
で始まり、次にbar
、dog
、またはcat
のいずれかで始まるすべてのファイルを照合します。しかし、bog
またはcog
またはcar
のような他のものが存在する場合、[〜#〜] not [〜#〜]一致する必要があります。
[a-z][a-z][a-z]
すると、一致します...
私はすでに次のようなことを試しました:
NAME="FOO[0-9][0-9]_(bar|dog|cat)"
or
NAME="FOO[0-9][0-9]_bar|dog|cat"
or
NAME="FOO[0-9][0-9]_[bar|dog|cat]"
or
NAME="FOO[0-9][0-9]_'bar|dog|cat'"
しかし、正規表現に関するドキュメントでは、完全に一致するものを見つけることができませんでした。
使用するメインスクリプトははるかに複雑で、さまざまなサブプロセスがハングしているため、1行で記述する必要があります。
これは可能ですか...?
文字列の一致のみを使用する場合は、=~
(拡張正規表現に一致する)を使用する必要があります。
if [[ "${FILENAME}" =~ "FOO[0-9][0-9]_(bar|dog|cat)" ]]
または
NAME="FOO[0-9][0-9]_(bar|dog|cat)"
if [[ "${FILENAME}" =~ ${NAME} ]]
オリジナルに合わせるため。
==
は常にグロビング一致(またはグロブが無効になっている場合は完全一致)であり、正規表現では使用できません。
または、スクリプトにさらに変更を加えることができる場合は、GNU find
を使用していると想定して、find
でフィルタリングできます。
find ${DIR} -maxdepth 1 -type f -regextype posix-extended -regex ".*/FOO[0-9][0-9]_(bar|dog|cat)\.[Dd][Oo][Cc]"
(-regextype posix-extended
はfind
に拡張正規表現を使用することを伝えます。.*/
はファイル名だけでなくパス全体と一致するため、正規表現自体は-regex
で始まります。)
find
の出力をループしないでください。代わりにfind
を使用して、パス名でフィードするスクリプトを実行します。
_#!/bin/bash
topdir='/search/path'
pattern='FOO[0-9][0-9]_(bar|dog|cat)'
find "$topdir" -type f -maxdepth 1 -iname '*.doc' -exec bash -c '
pattern=$1; shift
for pathname do
stem=$( basename "${pathname%.*}" )
if [[ "$stem" =~ $pattern ]]; then
printf "Found %s\n" "$pathname"
else
printf "No match in %s\n" "$pathname"
fi
done' bash "$pattern" {} +
_
find
で_-iname
_を使用すると、ファイル名で大文字と小文字を区別しない一致が行われることに注意してください。
関連:
または、bash
を使用して簡単に:
_#!/bin/bash
topdir='/search/path'
pattern='FOO[0-9][0-9]_(bar|dog|cat)'
shopt -s globstar nullglob
for pathname in "$topdir"/**/*.[Dd][Oo][Cc]; do
stem=$( basename "${pathname%.*}" )
if [[ "$stem" =~ $pattern ]]; then
printf "Found %s\n" "$pathname"
else
printf "No match in %s\n" "$pathname"
fi
done
_
または、全体でファイル名グロブを使用する:
_#!/bin/bash
topdir='/search/path'
shopt -s globstar nullglob extglob
for pathname in "$topdir"/**/*FOO[0-9][0-9]_@(bar|dog|cat)*.[Dd][Oo][Cc]
do
printf "Found %s\n" "$pathname"
done
_
globstar
は、_**
_グロブパターンを有効にします。これは、_*
_のように機能しますが、パス名のスラッシュ全体で一致します。nullglob
は、一致しないグロブパターンを空の文字列に展開します。extglob
は、いくつかの拡張globパターンを使用可能にします。これらの中には、括弧内のパターンのいずれかに一致する@(...)
があります。ワンライナーの場合は、
_shopt -s globstar nullglob extglob; printf 'Found %s\n' "$topdir"/**/*FOO[0-9][0-9]_@(bar|dog|cat)*.[Dd][Oo][Cc]
_
しかし、一致が見つからなかった場合でも、文字列Found
(1行に1つだけ)が出力されます。