I'm trying to write a script to automatically update my .ssh/config. Basically it's an ssh management tool that will add an .ssh/config entry for an input computer, user, etc.
Question:
Are there any tools available (like sed, or awk) for automatically inserting around or removing all instances of multi-line strings?
For example with the sed command:
# inserts "stuff" in the line above "single-line-pattern" in file
sed -i.bkp "/single-line-pattern/i stuff" file
# inserts "stuff" in the line below "single-line-pattern" in file
sed -i.bkp "/single-line-pattern/a stuff" file
# removes all instances of "single-line-pattern" from file
sed -i.bkp "/single-line-pattern/d" file
Possible Work Around
A hacky workaround for deleting all pattern instances is to invert the problem and find all non-instances, print those to a new file, and then delete the old file. Ignoring appending above an entry (because I deleted them all) I just append to the end of the file in a fixed order.
That being said this does not answer the above question, or give examples of such tools or sed/awk functions that work with multi-line strings.
My Solution
The hacky script that works for me is given below. You'll note that I use awk and it handles the multi-line problem well. It's just that as far as I know, awk does not provide many tools for manipulating or working around this phrase like the sed examples given above.
# create backup of file
cp $FILE $FILE.bak
# delete previous .tmp file
if [ -f $FILE.tmp ]; then
rm $FILE.tmp
fi
# if the expression is not in the paragraph, append it to $FILE.tmp
awk -v RS="" -v expr1="Host $COMPUTER" -v expr2="Match originalhost \
$COMPUTER" -v user="User $USER" \
'{ if (! (($0 ~ expr1 || $0 ~ expr2) && $0 ~ user)) print$0 "\n"}' \
$FILE >> $FILE.tmp
mv $FILE.tmp $FILE
My Problem Space
A matching set of paragraphs in $FILE for $COMPUTER="compy" and $USER="harpo" is given below. One could imagine entries for other computers or even for other users on the same computer (hence checking for both COMPUTER and USER matches).
Match originalhost compy exec /usr/local/bin/superscript.sh
HostName 192.168.0.101
User harpo
Port 22
IdentityFile /home/harpo/.ssh/id_rsa
Host compy
HostName 123.123.123.123
User harpo
Port 33
IdentityFile /home/harpo/.ssh/id_rsa
.ssh/configexcept that any entry with matching COMPUTER and USER would be deleted, and the paragraph would be appended to the end of the file. Consider a partially completed paragraph like one without an IdentityFile. I want to delete an existing entry to handle that, or any other permutation of error. I would say that it might just be better to focus on those enumerated questions?.ssh/configfile. Think of sshing to many machines and wanting an easy way to add new machines to your list of aliases. TheMatch originalhostbit runs a script to check if I'm behind a local network and thus use a local IP. Hope this helps!perlorawk, and not usingshcode at all - both have good support for reading files a paragraph at a time, and doing regex matches and/or substitutions on each paragraph. BTW, you can split a paragraph into lines by splitting on\nnewline characters if you need to. Bothawkandperlhavesplit()functions that can be used for this.