2

目前,我有一个功能齐全的 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"

我怎样才能改变我现有的命令来最好地完成这个?

4

2 回答 2

3

以您的主题为指导,这是使用 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'' 之间没有空格" 和 "' 在那里。

于 2013-03-29T18:09:35.990 回答
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"
于 2013-03-29T17:43:56.620 回答