只有在存在变量时才进行删除

时间:2014-11-05 16:07:07

标签: bash shell sed

我有这个表达:

// Initially variables set to "" before process

HOSTS_APACHE=""

HOSTS=""

// Some process ...

export HOSTS_CANAL_TMP=$(echo $HOSTS | sed "s/$HOSTS_APACHE//")

当一组主机中存在apache主机(处理后)时,它运行良好。但是当我有一组主机($HOSTS)并且我没有任何apache主机要排除时,它不起作用。

所以我需要一个类似的表达来执行$HOSTS_APACHE的SED,以防$HOSTS中存在apach,并且在没有任何事情的情况下不做任何事情。

现在在$HOSTS_APACHE

中排除$HOSTS时出现错误
sed: -e expression #1, char 0: no previous regular expression

2 个答案:

答案 0 :(得分:2)

编辑:如果我正确收集OP,则问题 - 或许是次要问题 - 是HOSTS_APACHE是无序,以空格分隔的主机列表或主机名。在这种情况下,解决方案是:

if [ -n "$HOSTS_APACHE" ]; then
    HOSTS_CANAL_TMP=$(echo $HOSTS | sed "s/${HOSTS_APACHE// /\\|}//g")
else
    HOSTS_CANAL_TMP=$HOSTS
fi

说明:

如果HOSTS_APACHE"bar baz",则${HOSTS_APACHE// /\\|}将为"baz\|bar"。使用双//的变量扩展是"的全局替换。 " (空格字符)\|

旧帖子:

实现这一目标的方法不止一种:

HOSTS_CANAL_TMP=$(echo $HOSTS |
    if [ -n "$HOSTS_APACHE" ]; then
        sed "s/$HOSTS_APACHE//"
    else
        cat # pass through
    fi)
如果[ -n STRING ] n 长度为零,则

STRING会返回0。

|if ...; fi工作的原因是因为if结构充当接收STDIN并写入STDOUT的微型程序。它调用哪个程序来处理I / O由if子句选择。

或者,您可以在子shell外部使用if-then-else结构:

if [ -n "$HOSTS_APACHE" ]; then
    HOSTS_CANAL_TMP=$(echo $HOSTS | sed "s/$HOSTS_APACHE//")
else
    HOSTS_CANAL_TMP=$HOSTS
fi

答案 1 :(得分:1)

你根本不需要sed

export HOSTS_CANAL_TMP=${HOSTS//"$HOSTS_APACHE"/}

${var//str/subst}语法是特定于Bash的(但是在分配之前将export放在一边,所以我在这里猜测这是安全的。)

但是,整个问题陈述看起来应该使用数组。

HOSTS=(foo bar baz)
HOSTS_CANAL_TMP=("${HOSTS[@]/#$HOSTS_APACHE}")

双引号是为了安全,但会导致HOSTS_CANAL_TMP中的空元素。如果你知道HOSTS中的值可以安全地使用而没有引号,你可以通过取出双引号来解决这个问题。