我正在编写一个bash脚本来自动完成一些任务。我要做的一件事就是在目录中的文件名中搜索一个模式,然后遍历结果。
当我运行此脚本时:
data=$(ls $A_PATH_VAR/*.ext | grep -o '201601[0-9]\{2\}\|201602[0-9]\{2\}')
echo $data
我得到了预期的结果 - 在$A_PATH_VAR/
中扩展名为.ext
的文件名中找到的所有匹配项的列表。但是,当我将所述模式存储在变量中然后使用它时,如下所示:
startmo=201601
endmo=201602
mo=$((startmo+1))
grepstr="'$startmo[0-9]\{2\}"
while [ $mo -le $endmo ]
do
grepstr="$grepstr\|$mo[0-9]\{2\}"
mo=$((mo+1))
done
grepstr="$grepstr'"
echo $grepstr # correct
data=$(ls $A_PATH_VAR/*.ext | grep -o $grepstr)
echo $data
$grepstr
中的模式已正确回显 - 也就是说,它包含值'201601[0-9]\{2\}\|201602[0-9]\{2\}'
,但$data
为空。这是为什么?
我的解决方案:
mo=$((startmo+1))
grepstr="($startmo[0-9][0-9]"
while [ $mo -le $endmo ]
do
grepstr="$grepstr|$mo[0-9][0-9]"
mo=$((mo+1))
done
grepstr="$grepstr)"
files=$(ls $A_PATH_VAR/*.ext)
setopt shwordsplit
for file in $files
do
if [[ $file =~ $grepstr ]]
then
date=$BASH_REMATCH
fi
...
done
答案 0 :(得分:6)
在下面,我忽略了你的输入源是ls
,除了这个开头的注释ls
should not be used in this manner和find
(在GNU扩展形式中,它包含一个应该考虑-regex
运营商)。
在:
pattern="'pattern'"
grep $pattern
...双引号("
)是 syntactic - 它们在解析阶段被shell使用,而其中的单引号是< em> literal - 外部语法引号指定其中的所有内容都被视为字符串的一部分(解析双引号内容的规则不同)。
因此,当您运行grep $pattern
时,会发生以下情况:
$pattern
的内容在IFS中的任何字符上都会被分成单词。默认情况下,IFS仅包含空格;但是,如果您有IFS=a
,则会将其分为单词"pa
和单词ttern"
pattern
包含"hello * world"
,并且您在空白处有一个IFS解析的默认值,那么我们就会分成"hello
,*
和{ {1}} - 然后将world"
替换为当前目录中的文件列表。显然,你不想要这个。因此,如果您的目标是防止字符串拆分和全局扩展,请仅使用语法引号:
*
顺便说一句,如果我有这个任务,我可以按如下方式编写它[以避免需要为每个可能的日期范围手工构建一个正则表达式]:
pattern="pattern"
grep "$pattern"