如何处理包含“;”的变量?

时间:2011-09-13 15:11:05

标签: bash debian

我有一个包含“hallo; welt;”之类的行的配置文件我想对这个文件做一个grep。 每当我尝试类似偶数行=“$ 1; $ 2”的grep "$1;$2" my.configecho "$1;$2之类的内容时,我的脚本会失败,例如:

  

:命令not found95:第155行:= hallo ...

我怎么能告诉bash忽略;在评估“......”块时?

编辑:我的代码示例。

# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)

# do some stuff on the permissions

# replace old line with new line
nline="$1;$2;$reads;$writes;$admins"
sed -i "s/$line/$nline/g" $TEMPPERM

我的脚本应该像这样调用:sh script“table”“a.b。*。>”

编辑:另一个更简单的例子

$test=$(grep "$1;$2;" temp.authorization.config)

临时文件:

table;pattern;read;write;stuff

调用sh test.sh表格模式导致:: command not foundtable;pattern;read;write;stuff

4 个答案:

答案 0 :(得分:4)

不要在bash的赋值左侧使用$ - 如果你这样做,将替换变量的当前值而不是赋值给它。也就是说,使用:

test=$(grep "$1;$2;" temp.authorization.config)

而不是:

$test=$(grep "$1;$2;" temp.authorization.config)

编辑:同样,变量扩展应该是双引号,除非有充分的理由。例如,使用:

reads=$(echo "$line" | cut -d';' -f3)

而不是:

reads=$(echo $line | cut -d';' -f3)

这对于分号无关紧要,但对空格,通配符和其他一些内容很重要。

答案 1 :(得分:3)

引号内的;对于bash没有任何意义。但是,如果$ 1本身包含双引号,那么你最终会得到

grep "something";$2"

将被bash解析为两个单独的命令:

grep "something"   ;     other"
^---command 1----^    ^----command 2---^

显示请准确显示您的脚本在发生错误的位置周围正在做什么,以及您正在为其提供哪些数据。

答案 2 :(得分:1)

反示例:

$ cat file.txt
hello;welt;
hello;world;
hell;welt;  
$ cat xx.sh
grep "$1;$2" file.txt
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
$

您尚未准确地对问题进行分类。


  

如果您尝试将grep的结果分配给变量(就像我一样),那么您的示例就会中断。

请说明你的意思。使用与以前相同的数据文件并进行分配,这是我得到的输出:

$ cat xx.sh
grep "$1;$2" file.txt
output=$(grep "$1;$2" file.txt)
echo "$output"
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
++ grep 'hello;welt' file.txt
+ output='hello;welt;'
+ echo 'hello;welt;'
hello;welt;
$

似乎适合我。它还说明了为什么这个问题需要一个明确的,完整的,可执行的,最小的例子,以便我们可以看到提问者所做的事情与人们回答问题的想法不同。


我看到你提供了一些示例代码:

# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)

$line=$(grep ...)行是错误的。您应该在$之前省略line。虽然它在语法上是正确的,但它意味着'分配给$line grep命令的结果存储在$line中的变量。这不太可能是你的想法。它偶尔会很有用。然而,这些场合很少见,而且只适用于那些知道自己在做什么以及能够准确记录他们正在做什么的人。

为了安全起见,我还要将echo值括在# find entry line=$(grep "$1;$2;" $PERMISSIONSFILE) # split line reads=$( echo "$line" | cut -d';' -f3) writes=$(echo "$line" | cut -d';' -f4) admins=$(echo "$line" | cut -d';' -f5) 行的双引号中。它可能不是严格必要的,但它是简单的保护性编程。

这些变化导致:

{{1}}

你的其余部分很好。

答案 3 :(得分:0)

您似乎正在尝试读取以分号分隔的文件,并标识以“table; pattern;”开头的行table是您指定的字符串,而pettern是正则表达式grep将理解。一旦识别出行,您希望用不同的数据替换第3,第4和第5个字段,并将更新的行写回文件。

这听起来不错吗?

如果是,请尝试此代码

#!/bin/bash

in_table="$1"
in_pattern="$2"
file="$3"

while IFS=';' read -r -d$'\n' tuple pattern reads writes admins ; do
    line=$(cut -d: -f1<<<"$tuple")
    table=$(cut -d: -f2<<<"$tuple")

    # do some stuff with the variables
    # e.g., update the values
    reads=1
    writes=2
    admins=12345

    # replace the old line with the new line
    sed -i'' -n $line'{i\
'"$table;$pattern;$reads;$writes;$admins"'
;d;}' "$file"
done < <(grep -n '^'"${in_table}"';'"${in_pattern}"';' "${file}")

我选择在此处按行号更新,以避免替换左侧的未知字符问题。