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