当sed输出从文件分配给变量时,echo是不同的

时间:2012-12-20 09:54:19

标签: file bash shell sed echo

我正在编写一个shell脚本,它使用sed基于模式分割字符串行。

    #pattern 'string1','string2','string3'

    cat $FILENAME | while read LINE
    do

    firstPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
    secondPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
    thirdPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )

    done

我能够使用单独的回声打印它们,但是如果我将它们放在一个回声中,如下所示

    #if LINE from FILE is '123','abc','hello'

    echo "$firstPart $secondPart"
    #this prints " abc" instead of "123 abc"

    #try appending a string on echo
    echo "$firstPart -"
    #this prints " -3" instead of "123 -"

当我尝试在代码中使用常量字符串中的sed时,echo似乎很好。

    #Correct Echo
    SOMESTRING='123','abc','hello'

    firstPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
    secondPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
    thirdPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )

    echo "$firstPart $secondPart"
    #this prints "123 abc"

当输入是来自FILE的LINE时,它是sed的正确行为吗?我怎样才能让它表现得好像在代码中包含并声明了LINE(就像我的第二个例子)。

4 个答案:

答案 0 :(得分:2)

在我看来,你的字符串中嵌入了回车符(有时写成\r)。因此当你执行echo "$firstPart -",其中firstPart =“123 \ r \ n”时,它会打印两行:

123
 -

...第二个“线”印在第一个上面(并覆盖)。我的猜测是你用一个文本编辑器编辑了脚本,该文本编辑器使用DOS样式的行结尾(即每行以回车符结束后跟换行),但shell需要unix样式的行结尾(只是换行)并处理回车作为命令的一部分(例如firstPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )\r,其中包括firstPart中的\r

如果这是问题,在脚本上运行dos2unix应该修复它(然后切换到不使用DOS样式行结尾的编辑器)。

答案 1 :(得分:0)

当你说SOMESTRING='123','abc','hello'进行bash时,它会删除单引号:

$ echo "$SOMESTRING"
123,abc,hello

如果你想保留它们,你需要说SOMESTRING="'123','abc','hello'"

这意味着您的sed模式不起作用,例如firstPart设置为空字符串。如果你从sed模式中删除单引号就可以了。

但我建议使用IFS拆分简单的分隔输入:

echo "'123','abc','hello'" | while IFS=, read a b c; do
  echo $a
  echo $b
  echo $c
done

或者更简洁:

while IFS=, read a b c; do echo -e "$a\n$b\n$c"; done <<< "'123','abc','hello'" 

输出:

'123'
'abc'
'hello'

答案 2 :(得分:0)

我不是专家,但我可以告诉你,当你使用“while”脚本时,while脚本中使用的变量在主脚本中不可用。

例: 如果在while循环中使用echo语句,则表明SED的解析很好。

您也可以使用以下语法在主脚本中公开这些变量。

while read LINE
do

firstPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\1/" )
secondPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\2/" )
thirdPart=$(echo "$LINE" | sed -r "s/'(.*)','(.*)','(.*)'/\3/" )
done < $FILENAME

答案 3 :(得分:0)

SOMESTRING='123','abc','hello'

firstPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\1/" )
secondPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\2/" )
thirdPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\3/" )