0

我在 bash 中有以下脚本:

#!/bin/bash
PSQL="psql -a -e -d users -U postgres --no-align -F$'\t' -c"
FILENAME="file.ext"
QUERY="select * from users limit 1;"
${PSQL} "${QUERY}" # > ${FILENAME}

-F$'\t'评估的方式不同。我们如何确保不会对字符串进行评估以返回不同的字符串,即最后我们希望将命令执行为:psql -a -e -d users -U postgres --no-align -F$'\t' -c "select * from users limit 1;" > file.ext

4

3 回答 3

1

解决问题的最佳方法是使用数组:

PSQL=( psql -a -e -d users -U postgres --no-align $'-F\t' -c )
FILENAME="file.ext"
QUERY="select * from users limit 1;"
"${PSQL[@]}" "${QUERY}" # > ${FILENAME}

解释。第一行定义了一个名为 PSQL 的新数组。你可以把它想象成:

PSQL[0] = psql
PSQL[1] = -a
PSQL[2] = -e
PSQL[3] = -d
PSQL[4] = users
PSQL[5] = -U
PSQL[6] = postgres
PSQL[7] = --no-align
PSQL[8] = -F<tab>
PSQL[9] = -c

在最后一行中,(双引号)术语"${PSQL[@]}"将扩展为构成数组的 10 个“单词”,PSQL而(双引号)术语"${QUERY}"将扩展为被select * from users limit 1;视为单个单词的字符串。为了让事情更清楚,我将向您展示扩展如何使用{并将}bash 在扩展行时看到的每个参数进行分组"${PSQL[@]}" "${QUERY}"

{ psql } { -a } { -e } { -d } { users } { -U } { postgres } { --no-align } { -F<tab> } { -c } { select * from users limit 1; }

评论。使用所有大写的变量名bash被认为是不好的做法。

于 2012-11-25T09:34:09.043 回答
-1

你需要确保

  • 制表符实际上存储在字符串中:
 PSQL="psql -a -e -d users -U postgres --no-align -F"$'\t'" -c"
  • 该 bash 在评估期间不会忽略选项卡:
OLDIFS="$IFS"
IFS=" "
${PSQL} "${QUERY}" # > ${FILENAME}
IFS="$OLDIFS"

IFS内部字段分隔符)被 bash 用来分隔各个参数,默认情况下包含制表符。您可以通过键入来验证这一点od -abc <<< "$IFS"

于 2012-11-25T10:08:39.707 回答
-2

解决方案非常简单,只需将最后一行改为:

eval "${PSQL} '${QUERY}' # > ${FILENAME}"
于 2012-11-25T09:43:25.450 回答