bash 导出表达式而不展开?

bash export expression without expanding?

我想做以下事情

export LOGS=//server/log_files/2014_*/server_{1,2,3}

所以我可以做类似

的事情

grep 'Exception' $LOGS/log.txt

我也试过别名,但我无法让它不展开。

我该怎么做?

如果没有 export,赋值的右侧既不会经过路径也不会展开大括号。

但是 export 会执行大括号扩展。您可以通过引用值来防止它:

export LOGS='//server/log_files/2014_*/server_{1,2,3}'

如果你想使用这样的值,你必须使用 eval:

eval grep 'Exception' $LOGS/log.txt

您正处于需要扩展 glob 的情况。这是这里最干净、语义最正确的,因为你想匹配文件名。由于我过于迂腐,我认为大括号扩展不是完成任务的正确工具。

# This defines a string that will glob
# No pathname expansions are performed at this step
logs_glob='//server/log_files/2014_*/server_@(1|2|3)'

# You need to activate extended globs with extglob
# To have a failure when no files match the glob, you need failglob
shopt -s failglob extglob

# Unquoted variable $logs_glob, as pathname expansion is desirable
grep 'Exception' $logs_glob

有些人会争辩说,使用 glob 技术您无法正确处理名称中的 spaces。事实上,您有两种方法:使用 ? 作为通配符(这将匹配 any 字符,因此特别是 spaces)或使用字符 class [[:space:]]。此字符 class 将匹配任何 space(常规 space、换行符、制表符等)


另一种技术是使用数组,仍然使用扩展的 glob。我认为这更清洁。

shopt -s extglob nullglob

# This will populate array with all matching filenames.
# If no matches, array is empty (since we shopted nullglob)
logs_array=( //server/log_files/2014_*/server_@(1|2|3) )

# Before you launch you command with the array, make sure it's not empty:
if ((${#logs_array[@]}!=0)); then
    # Observe the quotes for the expansion of the array
    grep 'Exception' "${logs_array[@]}"
fi