Bash: Output result of function into Sed parameters - bash

sed -i '$a\curl -s http://whatismyip.org/' file
Trying to find a way to pull the WAN IP and insert it into the last line of a file as illustrated above (not working of course). This will be utilized via command line.
sed -i '$a\test' file
This will insert "test" after the last line in "file" as utlilized but how could I output the result of a function or command in it's place within Sed's syntax? Any suggests (awk, perl, bash script?) are welcome!

sed isn't required here. Just use this:
curl -s http://whatsmyip.org >> your.file
Note that bash supports the >> redirection operator which appends a program's output to a file

hek2mgl has shown you how to solve this specific problem. To address the more general question, you can do:
var=$(some command line)
This sets the shell variable $var to the output of the command. Then you can subsitute this into sed with:
sed -i "\$a\\$var" file

Related

Bash script using sed to append line at end of file if line doesn't exist on mac

I need to use sed instead of echo and append to the end of a file: list.txt
list.txt has a list of directories:
/desktop/test1/file1
/desktop/test2/file1
I need to append another directory with slashes to this list.txt at the end of the file if that directory already doesn't exist in the list. Such as: /desktop/file1
The result should be:
/desktop/test1/file1
/desktop/test2/file1
/desktop/file1
I've tried using this script but am running into syntax errors with the a command which I've been seeing could be a mac issue?:
#!/bin/bash
if ! grep -q "/desktop/file1" user/admin/Desktop/list.txt; then
sed -i -e '$a/desktop/file1' user/admin/Desktop/list.txt
fi
The a command is used as a\ in standard sed and should be followed by a newline and the text to be written. The form you use is a GNU extension. So a standard sed command to do the job could be:
sed -i '' '$a\
/desktop/file1' user/admin/Desktop/list.txt
or
sed -i '' '$a\'$'\n''/desktop/file1' user/admin/Desktop/list.txt
using ANSI-C quoting in bash.

How to save a number to a variable and then output that value?

I want to use grep to count the number of W occurrences in the file.txt, save it as the variable WATER_NUMBER. Then append that number to the end of file.txt.
Following here,
I tried
#!/bin/bash -l
WATER_NUMBER="$(grep -c W file.txt)"
sed -i -e '$a\"${WATER_NUMBER}"' file.txt
but I got "${WATER_NUMBER}" printed out, instead of the number. Can I ask how to modify it?
The command
sed -i '$a\"${WATER_NUMBER}"' file.txt
will simply add the line "${WATER_NUMBER}" at the end of the file. You could try
sed -i "$ a\$WATER_NUMBER" file.txt
but this will still add the line $WATER_NUMBER. The problem is that the variable WATER_NUMBER is not expanded in the sed script. In order to pass its value to sed, place it outside the quoting, like this
sed -i '$ a\'$WATER_NUMBER file.txt
Edit: I actually wrote my answer yesterday without really thinking about the reason as to why the variable is not expanded. This morning I wondered why this is the case even though the variable is in double quotes as opposed to single quotes. The reason is actually just the coincidence that the \ from the append command is in front of the $ from the variable, thus escaping it. To prevent this, you need to escape the \. On the other hand, a backslash is actually not needed to separate the a from the line you want to add, hence
sed -i "$ a $WATER_NUMBER" file.txt
will do the job.
How to save a number to a variable?
WATER_NUMBER=42
How to append the variable content to a file?
echo $WATER_NUMBER >> file.txt

Replacing a value in a file using Shell Scripting

I want to replace a string in linux file with a variable value using Shell Script:
Tried doing this in shell script, but not working.
sed -i "s/$StrVal1/$StrVal2/" "$TargetFile"
Please help.
I think you forgot the "g" in the sed command. Works for me on my linux shell. You can also cat the file and then run the sed command.
First I define variables as shown below, on the prompt:
a='class'; b='CLASS'
Then I cat the file with a sed command:
cat a.txt | sed "s/$a/$b/g"
So my input file is like
class="pending">Count
class="completed">Count
My output with that command is like
CLASS="pending">Count:
CLASS="completed">Count:

Using shell script to copy script from one file to another

Basically I want to copy several lines of code from a template file to a script file.
Is it even possible to use sed to copy a string full of symbols that interact with the script?
I used these lines:
$SWAP='sudo cat /home/kaarel/template'
sed -i -e "s/#pointer/${SWAP}/" "script.sh"
The output is:
./line-adder.sh: line 11: =sudo cat /home/kaarel/template: No such file or directory
No, it is not possible to do this robustly with sed. Just use awk:
awk -v swap="$SWAP" '{sub(/#pointer/,swap)}1' script.sh > tmp && mv tmp script.sh
With recent versions of GNU awk there's a -i inplace flag for inplace editing if that's something you care about.
Good point about "&&". Here's the REALLY robust version that will work for absolutely any character in the search or replacement strings:
awk -v old="#pointer" -v new="$SWAP" 's=index($0,old){$0 = substr($0,1,s-1) new substr($0,s+length(old))} 1'
e.g.:
$ echo "abc" | awk -v old="b" -v new="m&&n" 's=index($0,old){$0 = substr($0,1,s-1) new substr($0,s+length(old))} 1'
am&&nc
There are two issues with the line:
$SWAP='sudo cat /home/kaarel/template'
The first is that, before executing the line, bash performs variable expansion and replaces $SWAP with the current value of SWAP. That is not what you wanted. You wanted bash to assign a value to SWAP.
The second issue is that the right-hand side is enclosed in single-quotes which protect the string from expansion. You didn't want to protect the string from expansion: you wanted to execute it. To execute it, you can use back-quotes which may look similar but act very differently.
Back-quotes, however, are an ancient form of asking for command execution. The more modern form is $(...) which eliminates some problems that back-quotes had.
Putting it all together, use:
SWAP=$(sudo cat /home/kaarel/template)
sed -i -e "s/#pointer/${SWAP}/" "script.sh"
Be aware, though, that the sed command may have problems if there are any sed-active characters in the template file.

replace a string in file using shell script

Suppose my file a.conf is as following
Include /1
Include /2
Include /3
I want to replace "Include /2" with a new line, I write the code in .sh file :
line="Include /2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf
But after running the sh file, It give me the following error
sed: -e expression #1, char 14: unknown option to `s'
If you are using a newer version of sed you can use -i to read from and write to the same file. Using -i you can specify a file extension so a backup will be made, incase something went wrong. Also you don't need to use the -e flag unless you are using multiple commands
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
I have just noticed that as the variables you are using are quoted strings you may want to use single quotes around your sed expression. Also your string contains a forward slash, to avoid any errors you can use a different delimiter in your sed command (the delimiter doesn't need to be a slash):
sed -i.bak 's|${line}|${rep}|g' /root/new_scripts/a.conf
You have to write the changes to a new file and then, move the new file over the old one. Like this:
line="Include 2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf > /root/new_scripts/a.conf-new
mv /root/new_scripts/a.conf-new /root/new_scripts/a.conf
The redirection (> /root/new_scripts/a.conf) wipes the contents of the file before sed can see it.
You need to pass the -i option to sed to edit the file in-place:
sed -i "s/${line}/${rep}/g" /root/new_scripts/a.conf
You can also ask sed to create a backup of the original file:
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
So, if you have to replace a substring in a file, you can use sed command like this, say we have a file as file.txt, so replacing a substring in it can be done like this
searchString="abc";
replaceString="def";
sed -i '' "s|$searchString|$replaceString|g" file.txt
This will all the occurrences of "abc" with "def" in file.txt. Also, this keeps a check for any / character present in the variables used, and with no backup file made.

Resources