ls | grep变量为正则表达式

时间:2016-06-16 20:31:56

标签: linux bash shell

我正在编写一个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

1 个答案:

答案 0 :(得分:6)

在下面,我忽略了你的输入源是ls,除了这个开头的注释ls should not be used in this mannerfind(在GNU扩展形式中,它包含一个应该考虑-regex运营商)。

在:

pattern="'pattern'"
grep $pattern

...双引号(")是 syntactic - 它们在解析阶段被shell使用,而其中的单引号是< em> literal - 外部语法引号指定其中的所有内容都被视为字符串的一部分(解析双引号内容的规则不同)。

因此,当您运行grep $pattern时,会发生以下情况:

  • $pattern的内容在IFS中的任何字符上都会被分成单词。默认情况下,IFS仅包含空格;但是,如果您有IFS=a,则会将其分为单词"pa和单词ttern"
  • 每个单词都以glob形式展开。因此,如果您的pattern包含"hello * world",并且您在空白处有一个IFS解析的默认值,那么我们就会分成"hello*和{ {1}} - 然后将world"替换为当前目录中的文件列表。

显然,你不想要这个。因此,如果您的目标是防止字符串拆分和全局扩展,请仅使用语法引号:

*
顺便说一句,如果我有这个任务,我可以按如下方式编写它[以避免需要为每个可能的日期范围手工构建一个正则表达式]:

pattern="pattern"
grep "$pattern"