getting a part of the output from a sed command - bash

I have this Command :
cat -n file.log | grep "Start new test" | tail -1 | cut -f 1 | xargs -I % sed -n %',$s/is not alive/&/p' file.log
That gives the output of the whole line :
Jan 19 23:20:33 s_localhost#file platMgt.xbin[3260]: blade 10 is not alive
Jan 19 23:20:33 s_localhost#file platMgt.xbin[3260]: blade 11 is not alive
how can I modify it to get the last part only :
blade 11 is not alive
can I modify that in a way to display :
Error:blade 11 is not alive ?
Thank you for your response

You can use cut to delimit it on the colons and then add the error message:
cat -n file.log | grep "Start new test" | tail -1 | cut -f 1 | xargs -I % sed -n %',$s/is not alive/&/p' file.log | cut -d: -f 4 | xargs -I % echo Error: %

To get the last part after colon awk is better tool:
s='Jan 19 23:20:33 s_localhost#file platMgt.xbin[3260]: blade 10 is not alive'
awk -F':' '{print "Error:" $NF}' <<< "$s"
OUTPUT:
blade 10 is not alive
EDIT: WIth your piped commands you can combine it as:
grep "Start new test" file.log|tail -1|awk -F':' '{print "Error:" $NF}'
PS: Though this whole thing is possible in awk itself.

The following obtains the the last ":" separated field with a sed command,
cat text.txt | sed 's/^.*: \([^:]*$\)/\1/g'

Related

grep search with filename as parameter

I'm working on a shell script.
OUT=$1
here, the OUT variable is my filename.
I'm using grep search as follows:
l=`grep "$pattern " -A 15 $OUT | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
The issue is that the filename parameter I must pass is test.log.However, I have the folder structure :
test.log
test.log.001
test.log.002
I would ideally like to pass the filename as test.log and would like it to search it in all log files.I know the usual way to do is by using test.log.* in command line, but I'm facing difficulty replicating the same in shell script.
My efforts:
var-$'.*'
l=`grep "$pattern " -A 15 $OUT$var | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
However, I did not get the desired result.
Hopefully this will get you closer:
#!/bin/bash
for f in "${1}*"; do
grep "$pattern" -A15 "$f"
done | grep -w $i | awk 'END{print $8}'

Feed line number to sed

I have a piped unix script which finally yields a line number to me in the subject file.
Now,I need to print out the file contents from this particular line to the end.
Is it possible to feed the line number to sed via xargs,for sed to print out the desired.
.....|tail -1 | cut -f 1 | xargs sed ...?
Is this possible?
..... | tail -1 | cut -f 1 | xargs -i sed -n '{},$p' your_file

how to parse a string in Shell script

I want to parse the following string in shell script.
VERSION=2.6.32.54-0.11.def
Here I want to get two value.
first = 263254
second = 11
I am using following to get the first value:
first=`expr substr $VERSION 1 9| sed "s/\.//g" |sed "s/\-//g"`
to get the second:
second=`expr substr $VERSION 10 6| sed "s/\.//g" |sed "s/\-//g"`
Using above code the output is:
first=263254
second=11
The result wont be consistent if version is changed to:
VERSION=2.6.32.54-0.1.def
Here second value will become 1d, but I want it give output of 1 only.
How can I directly parse the number after '-' and before '.d'?
$ first=$(echo $VERSION | cut -d- -f1 | sed 's/\.//g')
$ second=$(echo $VERSION | cut -d- -f2 | cut -d. -f2)
$ first=$(echo $VERSION | cut -d- -f1 | tr -d '.')
$ second=$(echo $VERSION | cut -d- -f2 | cut -d. -f2)
$ echo $first
263254
$ echo $second
11
you don't need multiple processes (sed|sed|sed...). single process with awk should work.
if you have VERSION=xxxx as string:
to get the first:
awk -F'[-=]' '{gsub(/\./,"",$2)}$0=$2'
to get the second:
awk -F'-|\\.def' '{split($2,a,".")}$0=a[2]'
test:
first:
kent$ echo "VERSION=2.6.32.54-0.1.def"|awk -F'[-=]' '{gsub(/\./,"",$2)}$0=$2'
263254
second
kent$ echo "VERSION=2.6.32.54-0.1.def"|awk -F'-|\\.def' '{split($2,a,".")}$0=a[2]'
1
kent$ echo "VERSION=2.6.32.54-0.1234.def"|awk -F'-|\\.def' '{split($2,a,".")}$0=a[2]'
1234
if you have VERSION=xxx as variable $VERSION:
first:
awk -F'-' '{gsub(/\./,"",$1)}$0=$1'
second:
awk -F'-|\\.def' '{split($2,a,".")}$0=a[2]'
test:
VERSION=2.6.32.54-0.1234.def
kent$ echo $VERSION|awk -F'-' '{gsub(/\./,"",$1)}$0=$1'
263254
7pLaptop 11:18:22 /tmp/test
kent$ echo $VERSION|awk -F'-|\\.def' '{split($2,a,".")}$0=a[2]'
1234
You should use regular expressions instead of the number of characters.
first=`sed 's/.//g' | sed 's/\(.*\)-.*/\1/'`
second=`sed 's/.//g' | sed 's/.*-\([0-9]*\).*/\1/'`
\(...\) are used to create a capturing group, and \1 output this group.
first=$(echo ${VERSION} | sed -e 's/^\([^-]*\)-0\.\([0-9]*\)\.def/\1/' -e 's/\.//g')
second=$(echo ${VERSION} | sed -e 's/^\([^-]*\)-0\.\([0-9]*\)\.def/\2/' -e 's/\.//g')
$ first=$(echo $VERSION | awk -F"\." '{gsub(/-.*/,"",$4);print $1$2$3$4}')
$ second=$(echo $VERSION | awk -F"\." '{print $5}' )

How to prevent bash for loop to transform string data

I want to filter out datestamps from the message log and delete all occurances:
(basicly this is a part of an usb history cleaner script, head -n1 added only becouse of testing)
delimiter=`echo $HOSTNAME | cut -f1 -d.`
for item in `egrep usb /var/log/messages | awk -F"$delimiter" '{print $1}' | uniq | head -n1`; do
echo ${item}
done
when I run this command:
egrep usb /var/log/messages | awk -F"$delimiter" '{print $1}' | uniq | head -n1
the output is fine:
Mar 31 03:25:03
but when it will be given back to the for loop, the data transfers like this becouse of the spaces:
Mar
31
03:25:03
the question is: how can I prevent this kind of behaviour?
Instead of:
for item in `whatever`; do
echo ${item}
done
use:
whatever |
while IFS= read -r item; do
echo "${item}"
done
but your whole script could be re-written as just:
awk -F"${HOSTNAME%%.*}" '/usb/ && !seen[$1]++ {print $1}' /var/log/messages

Use each line of piped output as parameter for script

I have an application (myapp) that gives me a multiline output
result:
abc|myparam1|def
ghi|myparam2|jkl
mno|myparam3|pqr
stu|myparam4|vwx
With grep and sed I can get my parameters as below
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//'
But then want these myparamx values as paramaters of a script to be executed for each parameter.
myscript.sh myparam1
myscript.sh myparam2
etc.
Any help greatly appreciated
Please see xargs. For example:
myapp | grep '|' | sed -e 's/^[^|]*//' | sed -e 's/|.*//' | xargs -n 1 myscript.sh
May be this can help -
myapp | awk -F"|" '{ print $2 }' | while read -r line; do /path/to/script/ "$line"; done
I like the xargs -n 1 solution from Dark Falcon, and while read is a classical tool for such kind of things, but just for completeness:
myapp | awk -F'|' '{print "myscript.sh", $2}' | bash
As a side note, speaking about extraction of 2nd field, you could use cut:
myapp | cut -d'|' -f 1 # -f 1 => second field, starting from 0

Resources