How to run a command in sed in Linux? - linux

sed -i 's/1.1.1.1/ `hostname -I | cut -f1 -d " "`/g' file.txt
Not able to overwrite IP address using sed command in a given file. How to run this (hostname -I | cut -f1 -d " ") command with sed command?

This might work for you (GNU sed):
sed -i '/1\.1\.1\.1/{s//$(hostname -I | cut -f1 -d " ")/;s/.*/echo "&"/e}' file
Place the commands between $(...) and then echo the line using the evaluate flag of the substitution command.

Just use a variable.
hn=$(hostname -I | cut -f1 -d" ") && sed -i "s/1\.1\.1\.1/$hn/g" file
Sed's e and s///e work on the entire pattern space, so it's just more trouble than it's worth.

Related

Sed unknown option to `s when i try to pass 2 variables

i have a problem with my sed command in my sh script.
I already tried without -i, replacing my file with a backup using > and cp, removing the simples quotes and trying with double after s/ and /g.
echo '=> Enabling Cryptodisk in GRUB'
sed -i 's/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/g' /etc/default/grub #Enabling Cryptodisk in GRUB
echo '=> Adding Preload_modules in GRUB'
sed -i 's/GRUB_PRELOAD_MODULES="part_gpt part_msdos"/GRUB_PRELOAD_MODULES="part_gpt part_msdos luks cryptodisk"/g' /etc/default/grub #Adding Preload_modules in GRUB
echo '=> Adding Linux CMDLINE in GRUB'
GUIDMAPPER=$(blkid | grep ^/dev/mapper | awk -F "\"" '{print $2}') #Get mapper GUID
GUIDSDA3=$(blkid | grep ^/dev/sda3 | awk -F "\"" '{print $2}') #Get sda3 GUID
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cryptdevice=${GUIDMAPPER}=${GUIDSDA3}:cryptroot root=/dev/mapper/cryptroot crypto=whirlpool:aes-xts-plain64:512:0:"/g' /etc/default/grub #Adding Linux CMDLINE in GRUB
The error is triggered for the last sed call, everything else work fine.
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cryptdevice=${GUIDMAPPER}=${GUIDSDA3}:cryptroot root=/dev/mapper/cryptroot crypto=whirlpool:aes-xts-plain64:512:0:"/g' /etc/default/grub
Tested so far... :
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cryptdevice='"$GUIDMAPPER"'='"$GUIDSDA3"':cryptroot root=/dev/mapper/cryptroot crypto=whirlpool:aes-xts-plain64:512:0:"/g' /etc/default/grub #Adding Linux CMDLINE in GRUB
Result
Thanks (sorry for my bad english)
Edit :
It works by escaping '\' in replacement.
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="cryptdevice='"$GUIDMAPPER"'='"$GUIDSDA3"':cryptroot root=\/dev\/mapper\/cryptroot crypto=whirlpool:aes-xts-plain64:512:0:"/g' /etc/default/grub #Adding Linux CMDLINE in GRUB
Thanks to Wiktor Stribiżew

Bash grep output filename and line no without matches

I need to get a list of matches with grep including filename and line number but without the match string
I know that grep -Hl will give only file names and grep -Hno will give filename with only matching string. But those not ideal for me. I need to get a list without match but with line no. For this grep -Hln doesn't work. I tried with grep -Hn 'pattern' | cut -d " " -f 1 But it doesn't cut the filename and line no properly.
awk can do that in single command:
awk '/pattern/ {print FILENAME ":" NR}' *.txt
You were pointing it well with cut, only that you need the : field separator. Also, I think you need the first and second group. Hence, use:
grep -Hn 'pattern' files* | cut -d: -f1,2
Sample
$ grep -Hn a a*
a:3:are
a:10:bar
a:11:that
a23:1:hiya
$ grep -Hn a a* | cut -d: -f1,2
a:3
a:10
a:11
a23:1
I guess you want this, just line numbers:
grep -nh PATTERN /path/to/file | cut -d: -f1
example output:
12
23
234
...
Unfortunately you'll need to use cut here. There is no way to do it with pure grep.
Try
grep -RHn Studio 'pattern' | awk -F: '{print $1 , ":", $2}'

How to combine sed 'sentences'? [duplicate]

This question already has answers here:
Combining two sed commands
(2 answers)
Closed 1 year ago.
I made this script:
xrandr | grep '*' | sed 's/\S*\(*+\)\S*//g'| sed 's/ //g' | sed 's/x.*//'
How can I combine the three sed commands:
sed 's/\S*\(*+\)\S*//g'
sed 's/ //g'
sed 's/x.*//'
into a single command?
With -e:
xrandr | grep '*' | sed -e 's/\S*\(*+\)\S*//g' -e 's/ //g' -e 's/x.*//'
Note that the grep is not necessary:
xrandr | sed -e '/\*/!d' -e 's/\S*\(*+\)\S*//g' -e 's/ //g' -e 's/x.*//'
You could put those commands in a file called sedscr for example, one per line as such:
s/x.*//
s/ //g
s/\S*\(*+\)\S*//g
And then call:
xrandr | grep '*' | sed -f sedscr
I prefer this method, just in case I want to add more commands in the future.
You can simply consider all sed commands as script and add a ; between commands :
xrandr | grep '*' | sed 's/\S*\(*+\)\S*//g ; s/ //g ; s/x.*//'
With newlines :
echo coobas | sed 's:c:f:
s:s:r:'
Without sed but just grep :
$ xrandr | grep -oP '^\s+\K\d+(?=.*?\*)'
1440
or with perl :
$ xrandr | perl -lne 'print $1 if /^\s+(\d+)(?=.*?\*)/'
1440
Another thing to consider is to make a sed config file (call it config.sed) listing all replacement rules. E.g.:
1,/^END/{
s/x.*//
s/ //g
s/\S*\(*+\)\S*//g
}
and then run
sed -f config.sed filein.txt > fileout.txt

Strange output from sed

I have some html files and want to extract only lines with containing these tags:
head
p
I used sed to extract these parts of the files, as follows:
grep "<head>" myfile.html | sed -e 's%\(head\)\(.*\)\(/head\)%title\2\/title%'
grep "<p>" myfile.html | sed -e 's%\(<p>\)\(.*\)\(</p\)\(>\)%\2\\%'
Everything is Ok, but I get "\" character at the end of each line. How I can overcome this problem?
In this command, you're telling it to add a backslash by including the double backslash:
sed -e 's%\(<p>\)\(.*\)\(</p\)\(>\)%\2\\%'
Try removing the backslashes:
sed -e 's%\(<p>\)\(.*\)\(</p\)\(>\)%\2%'
Also, you don't need grep:
sed -ne '/<p>/{s%\(<p>\)\(.*\)\(</p\)\(>\)%\2%;p}'
Don't use \ at the end of the replacement string:
grep "<p>" myfile.html | sed -e 's%\(<p>\)\(.*\)\(</p\)\(>\)%\2%'

How to extract version from a single command line in linux?

I have a product which has a command called db2level whose output is given below
I need to extract 8.1.1.64 out of it, so far i came up with,
db2level | grep "DB2 v" | awk '{print$5}'
which gave me an output v8.1.1.64",
Please help me to fetch 8.1.1.64. Thanks
grep is enough to do that:
db2level| grep -oP '(?<="DB2 v)[\d.]+(?=", )'
Just with awk:
db2level | awk -F '"' '$2 ~ /^DB2 v/ {print substr($2,6)}'
db2level | grep "DB2 v" | awk '{print$5}' | sed 's/[^0-9\.]//g'
remove all but numbers and dot
sed is your friend for general extraction tasks:
db2level | sed -n -e 's/.*tokens are "DB2 v\([0-9.]*\)".*/\1/p'
The sed line does print no lines (the -n) but those where a replacement with the given regexp can happen. The .* at the beginning and the end of the line ensure that the whole line is matched.
Try grep with -o option:
db2level | grep -E -o "[0-9]+\.[0-9]+\.[0-9]\+[0-9]+"
Another sed solution
db2level | sed -n -e '/v[0-9]/{s/.*DB2 v//;s/".*//;p}'
This one desn't rely on the number being in a particular format, just in a particular place in the output.
db2level | grep -o "v[0-9.]*" | tr -d v
Try s.th. like db2level | grep "DB2 v" | cut -d'"' -f2 | cut -d'v' -f2
cut splits the input in parts, seperated by delimiter -d and outputs field number -f

Resources