【问题标题】:Bash: Get command output with variables inside the commandBash:使用命令内的变量获取命令输出
【发布时间】:2020-03-22 20:20:23
【问题描述】:

我有一个 bash/shell 脚本,想将命令输出存储在一个变量(EXCLUDE_PATTERN)中,并且命令本身也包含变量(FOLDERS BUPATH)。

此命令的目标是将变量 FOLDERS 中的空格替换为 " --exclude="$BUPATH 以用于 tar强>命令

如果在脚本中定义了以下变量:

FOLDERS='folder1 folder2 folder3'
BUPATH='/opt/mypath'
CONFIG_BACKUP="/storage/backup.tar.gz"

FOLDER 是一个包含排除文件夹列表的变量

BUPATH 是一个带路径的变量

现在我想用以下 tar 命令的模式定义一个变量 EXCLUDE_PATTERN(尝试了 2 个变体):

EXCLUDE_PATTERN=`echo $FOLDERS | sed 's/\ /" --exclude="$BUPATH\//g'`
EXCLUDE_PATTERN=`echo $FOLDERS | sed 's/\ /" --exclude="${BUPATH}\//g'`

然后脚本运行tar命令:

tar -C \"$BUPATH\" --exclude=\"$BUPATH/$EXCLUDE_PATTERN\" -czf \"$CONFIG_BACKUP\" .

似乎变量 EXCLUDE_PATTERN 无法识别 BUPATH 变量:

tar -C "/opt/mypath" --exclude="/opt/mypath/folder1" --exclude="${BUPATH}/folder2" --exclude="${BUPATH}/folder3" -czf "/storage/config.tar.gz" .

预期的命令应该是这样的:

tar -C "/opt/mypath" --exclude="/opt/mypath/folder1" --exclude="/opt/mypath/folder2" --exclude="/opt/mypath/folder3" -czf "/storage/config.tar.gz" .

我希望有人能帮我解决这个问题:)

【问题讨论】:

  • 你为什么要转义那些双引号?
  • 我也试过不带引号,但没有区别(更新)
  • 为什么\" 逃避"?你真的有一个名为 " 的目录吗? cd ./\" 有效吗? cd ./\"/opt/mypath 有效吗?

标签: linux string bash shell variables


【解决方案1】:

FOLDERS='文件夹 1 文件夹 2 文件夹 3'

BUPATH='/opt/mypath'

CONFIG_BACKUP="/storage/backup.tar.gz"

预期的命令应该是这样的:

tar -C "/opt/mypath" --exclude="/opt/mypath/folder1" --exclude="/opt/mypath/folder2" --exclude="/opt/mypath/folder3" -czf “/storage/config.tar.gz”。

嗯,这很简单。我喜欢 xargs printf 来转换列表,例如。添加一些东西:

# creates a bash array from newline separated output
IFS=$'\n' tarexcludes=($(<<<"$FOLDERS" xargs -n1 printf "--exclude=%s/%s\n" "$BUPATH"))
echo tar -C "/opt/mypath" "${tarexcludes[@]}" -czf "$CONFIG_BACKUP" .

但您也可以选择唯一的 sed 命令分隔符:

tarexcludes=($(<<<"$FOLDERS" tr ' ' '\n' | sed "s~^~--exclude=$BUPATH/~"))

或者使用awk:

tarexcludes=($(<<<"$FOLDERS" tr ' ' '\n' | awk -v BUPATH="$BUPATH" '{print "--exclude=" BUPATH "/" $0}')

注意事项:

  • 不要使用反引号`。他们很沮丧,我不喜欢他们。 bash obsolete and deprecated syntax
  • &lt;&lt;&lt;"$FOLDERS" 是 bash 的 here string
  • tr ' ' '\n' 用空格代替换行符。所以它可以用 sed 解析。
  • tarexcludes=( ... ) 创建一个 bash 数组。 bashguide arrays
  • 您的命令不起作用,因为echo $FOLDERS 将在一行上输出,而 sed 会解析行。所以只需用换行符替换空格。或者,使用xrandr -n1printf "%s" $FOLDERS
  • 按照约定,大写变量名按照约定保留给环境导出的变量。在脚本中使用小写的变量名。

【讨论】:

    【解决方案2】:

    您也可以使用" # 的组合来代替' / 来解决您的问题。

    EXCLUDE_PATTERN=`echo $FOLDERS |  sed -e "s#\ #\" --exclude=$BUPATH\"/#g"`
    

    但这会输出:
    folder1" --exclude=/opt/mypath"/folder2" --exclude=/opt/mypath"/folder3

    要归档预期的输出,需要进行以下修改:

    EXCLUDE_PATTERN=`echo $FOLDERS |  sed -e "s#\(\S\+\)# --exclude=\"$BUPATH/\1\"#g"`
    

    这将输出:
    --exclude="/opt/mypath/folder1" --exclude="/opt/mypath/folder2" --exclude="/opt/mypath/folder3"

    有关更多信息,请阅读 StackOverflow 帖子:
    Escape a string for a sed replace pattern

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-26
      • 2012-03-02
      • 2014-06-27
      • 2018-02-02
      • 2018-10-01
      • 1970-01-01
      • 2015-06-19
      • 2012-07-16
      相关资源
      最近更新 更多