1

我正在编写一个 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

4 回答 4

2

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

123
 -

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

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

于 2012-12-20T12:22:24.820 回答
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'
于 2012-12-20T10:48:35.323 回答
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
于 2012-12-20T11:04:42.637 回答
0
SOMESTRING='123','abc','hello'

firstPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\1/" )
secondPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\2/" )
thirdPart=$(echo "$SOMESTRING" | sed "s/\([^,]*\),\([^,]*\),\([^,]*\)/\3/" )
于 2014-05-08T05:01:07.390 回答