Currently, I have a fully functional sed command that adds an item to a list in a specific text file in the following way ...
ITEMS="$ITEM1 $ITEM2 $ITEM3"
becomes the following when we wish to insert $ITEM4 ...
ITEMS="$ITEM1 $ITEM2 $ITEM3 $ITEM4"
The number of items in the list is not known; it is dynamic. And the dollar signs and quotes in that text are to be taken literally.
I use the following command to accomplish the addition to the list (variable $itemNum is assigned elsewhere) ...
sed "/^\s*ITEMS=/s/\"$/ \$ITEM$itemNum&/" file.txt
All this does, of course, is find the line starting with ITEMS= (and possibly with leading spaces) and replace the last double quote in that line with a space plus the desired item plus a double quote (to put the replaced double quote back in place). However, I have an additional case where the ITEMS list could be empty like so ...
ITEMS=""
and in this case, my command would insert $ITEM4 at the end of the list like so ...
ITEMS=" $ITEM4"
However, I want my command to be able to account for an empty list and not put the leading space when the list is indeed empty, so it just looks like ...
ITEMS="$ITEM4"
How could I alter my existing command to best accomplish this?
Taking your subject as a guide, here is one way to do it conditionally with sed:
sed -e '/^\s*ITEMS=/{s/=""/="$ITEM'"$itemNum"'"/;t;s/"$/ $ITEM'"$itemNum&/;}" file.txt
The main change is we try to substitute empty quotes ("") first. If that succeeds, the conditional branch t sends us to the end of the script, bypassing the other substitution. The second substitution only occurs if the first fails. I've changed the quoting to get rid of some of the "leaning toothpicks", but it's about 66% your original command.
Edit: The "leaning toothpicks" thing by OP's request
The original put the entire sed script line in double quotes so all " and most $ had to be escaped with backslashes. Rewriting my version like that looks like this:
sed -e "/^\s*ITEMS=/{s/=\"\"/=\"\$ITEM$itemNum\"/;t;s/\"$/ \$ITEM$itemNum&/;}" file.txt
I just find all those backslashes distracting, so I put as much of it into single quotes as I could, leaving only $itemNum in double quotes. In a shell script, if two strings are adjacent, they get stuck together so var1=QRS; var2='ABC'$var1'XYZ' leaves var2 set to 'ABCQRSXYZ' - if you think there's a chance the variable could contain a space, then it is best to quote it: var1=QRS; var2='ABC'"$var1"'XYZ' (no space between '" and "' in there.
in this situation, awk is more flexible:
awk -F'"' -vn="$itemNum" '/^\s*ITEMS=/{sub(/"$/,($2?" ":"")"$ITEM"n"&")}1' file
test:
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With