当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

我可以使用单独的echo来打印它们,但是如果我将它们放在一个echo中,如下所示

    #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一样(就像我的第二个例子)。

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

123
 -

…第二"行"印在第一行的上面(并覆盖第一行)。我的猜测是,你已经用一个文本编辑器编辑了脚本,使用dos风格的行结尾(即每行以回车结束,然后换行),但是shell期望unix风格的行结尾(只是换行),并将回车作为命令的一部分(例如firstPart=$(echo "$SOMESTRING" | sed -r "s/'(.*)','(.*)','(.*)'/1/" )r,它将包括r在firstPart。

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

当您输入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 "$an$bn$c"; done <<< "'123','abc','hello'" 
输出:

'123'
'abc'
'hello'

我不是专家,但我可以告诉你,当你在管道"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
SOMESTRING='123','abc','hello'
firstPart=$(echo "$SOMESTRING" | sed "s/([^,]*),([^,]*),([^,]*)/1/" )
secondPart=$(echo "$SOMESTRING" | sed "s/([^,]*),([^,]*),([^,]*)/2/" )
thirdPart=$(echo "$SOMESTRING" | sed "s/([^,]*),([^,]*),([^,]*)/3/" )

最新更新