有条件的sed替代

时间:2013-03-29 17:28:04

标签: bash

目前,我有一个功能齐全的sed命令,可以通过以下方式将项目添加到特定文本文件的列表中...

ITEMS="$ITEM1 $ITEM2 $ITEM3"
当我们希望插入$ITEM4 ...

时,

成为以下内容

ITEMS="$ITEM1 $ITEM2 $ITEM3 $ITEM4"

列表中的项目数量未知;它是动态的。而该文中的美元符号和引用将按字面意思进行。

我使用以下命令完成对列表的添加(变量$itemNum在其他地方分配)...

sed "/^\s*ITEMS=/s/\"$/ \$ITEM$itemNum&/" file.txt

当然,所有这一切都是找到以ITEMS=开头的行(并且可能带有前导空格),并用空格加上所需的项目加上双引号替换该行中的最后一个双引号(到将替换的双引号放回原位)。但是,我还有一个案例,其中ITEMS列表可能是空的,如此......

ITEMS=""

在这种情况下,我的命令会在列表末尾插入$ITEM4,如此...

ITEMS=" $ITEM4"

但是,我希望我的命令能够计算一个空列表,而不是在列表确实为空时放置前导空格,所以它看起来像......

ITEMS="$ITEM4"

我怎样才能改变现有命令以达到最佳效果?

2 个答案:

答案 0 :(得分:2)

以您的主题为指导,这是使用sed有条件地执行此操作的一种方法:

sed -e '/^\s*ITEMS=/{s/=""/="$ITEM'"$itemNum"'"/;t;s/"$/ $ITEM'"$itemNum&/;}" file.txt

主要的变化是我们首先尝试替换空引号(“”)。如果成功,则条件分支t将我们发送到脚本的末尾,绕过另一个替换。第二次替换仅在第一次失败时发生。我已经改变了引用以摆脱一些“倾斜的牙签”,但它大约是原始命令的66%。

编辑:OP的请求“倾斜的牙签”事物

原文将整个sed脚本行放在双引号中,所以所有“和大多数$都必须使用反斜杠进行转义。重写我的版本就像这样:

sed -e "/^\s*ITEMS=/{s/=\"\"/=\"\$ITEM$itemNum\"/;t;s/\"$/ \$ITEM$itemNum&/;}" file.txt

我发现所有那些反斜杠都让人分心,所以我尽可能多地将它放入单引号中,只留下$ itemNum用双引号。在shell脚本中,如果两个字符串相邻,它们会卡在一起,因此var1=QRS; var2='ABC'$var1'XYZ'将var2设置为'ABCQRSXYZ' - 如果您认为变量可能包含空格,那么最好引用它: var1=QRS; var2='ABC'"$var1"'XYZ'(“和”之间没有空格。

答案 1 :(得分:1)

在这种情况下,awk更灵活:

awk -F'"' -vn="$itemNum" '/^\s*ITEMS=/{sub(/"$/,($2?" ":"")"$ITEM"n"&")}1' file

试验:

kent$  itemNum=4 
kent$  echo 'ITEMS=""'|awk -F'"' -vn="$itemNum" '/^\s*ITEMS=/{sub(/"$/,($2?" ":"")"$ITEM"n"&")}1'
ITEMS="$ITEM4"
kent$  echo 'ITEMS="$ITEM1 $ITEM2 $ITEM3"'|awk -F'"' -vn="$itemNum" '/^\s*ITEMS=/{sub(/"$/,($2?" ":"")"$ITEM"n"&")}1'                                                       
ITEMS="$ITEM1 $ITEM2 $ITEM3 $ITEM4"