我正在编写一个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(就像我的第二个例子)。
答案 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/" )