Need to grab data inbetween tilde character - linux

Can any one advise how to search on linux for some data between a tilde character. I need to get IP data however its been formed like the below.
Details:
20110906000418~118.221.246.17~DATA~DATA~DATA

One more:
echo '20110906000418~118.221.246.17~DATA~DATA~DATA' | sed -r 's/[^~]*~([^~]+)~.*/\1/'

echo "20110906000418~118.221.246.17~DATA~DATA~DATA" | cut -d'~' -f2
This uses the cut command with the delimiter set to ~. The -f2 switch then outputs just the 2nd field.
If the text you give is in a file (called filename), try:
grep "[0-9]*~" filename | cut -d'~' -f2

With cut:
echo "20110906000418~118.221.246.17~DATA~DATA~DATA" | cut -d~ -f2
With awk:
echo "20110906000418~118.221.246.17~DATA~DATA~DATA"
| awk -F~ '{ print $2 }'

In awk:
echo '20110906000418~118.221.246.17~DATA~DATA~DATA' | awk -F~ '{print $2}'

Just use bash
$ string="20110906000418~118.221.246.17~DATA~DATA~DATA"
$ echo ${string#*~}
118.221.246.17~DATA~DATA~DATA
$ string=${string#*~}
$ echo ${string%%~*}
118.221.246.17

one more, using perl:
$ perl -F~ -lane 'print $F[1]' <<< '20110906000418~118.221.246.17~DATA~DATA~DATA'
118.221.246.17
bash:
#!/bin/bash
IFS='~'
while read -a array;
do
echo ${array[1]}
done < ip
If string is constant, the following parameter expansion performs substring extraction:
$ a=20110906000418~118.221.246.17~DATA~DATA~DATA
$ echo ${a:15:14}
118.221.246.17
or using regular expressions in bash:
$ echo $(expr "$a" : '[^~]*~\([^~]*\)~.*')
118.221.246.17
last one, again using pure bash methods:
$ tmp=${a#*~}
$ echo $tmp
118.221.246.17~DATA~DATA~DATA
$ echo ${tmp%%~*}
118.221.246.17

Related

How to search and delete a pattern from a line?

I need to write a simple bash script that takes a text line
some-pattern something-else
and erases some-pattern and returns only something-else. I wrote a script to do the opposite with grep -o, but I don't know how I could do with this case. Any help is very much appreciated.
sample input:
"SNMPv2::sysLocation.0 = STRING: someLocation"
Desired Output:
"someLocation"
Considering " are NOT in your sample Input_file and expected output, could you please try following with GNU grep.
grep -oP '.*STRING: \K(.*)' Input_file
someLocation
For \K explanation:
\K is a PCRE extension to regex syntax discarding content prior to
that point from being included in match output
You can use sed to delete the part in front of what you want to keep.
Given:
$ echo "$s"
"SNMPv2::sysLocation.0 = STRING: someLocation"
You can do:
$ echo "$s" | sed -nE 's/^.*(someLocation)/\1/p'
someLocation
And if you want to add quotes:
$ echo "$s" | sed -nE 's/^.*(someLocation)/"\1"/p'
"someLocation"
If the portion after STRING: is variable, not fixed, you can use STRING: and the capture anchor:
$ echo "$s" | sed -nE 's/^.*STRING:[[:space:]]*(.*)/"\1"/p'
"someLocation"
Or, sed to capture and print the last word after the last space:
$ echo "$s" | sed -nE 's/([^[:space:]]*$)/\1/p'
You can also use awk if the last word is space separated from the other fields:
$ echo "$s" | awk '{print $NF}'
Or a pipeline with cut and rev works too:
$ echo "$s" | rev | cut -d' ' -f 1 | rev
You can use: echo ${STRING} | awk -F" " '/someLocation/ { print $NF }'
-F will use space (represented by double-quotes with space between them) as separator; /someLocation/ will search for your location; { print $NF } will show the last part of your string (which, I believe, is the place where location is.

printing "grep -o" output in single line

How to print output of grep -o in a single line ? I am trying to print :
$ echo "Hello Guys!" |grep -E '[A-Z]'
Hello Guys!
$ echo "Hello Guys!" |grep -Eo '[A-Z]' <----Multiple lines
H
G
$ echo "Hello Guys!" |grep -Eo '[A-Z]'
Desired output:
HG
I am able to cheaply achieve it using following command ,but the issue is that number of letters(3 in this case) could be dynamic. So this approach cannot be used.
echo "HEllo Guys!" |grep -oE '[A-Z]' |xargs -L3 |sed 's/ //g'
HEG
You could do it all with this sed instruction
echo "Hello Guys!" |sed 's/[^A-Z]//g'
UPDATE
Breakdown of sed command:
The s/// is sed's substitute command. It simply replaces the first RegEx (the one between the first and the second slash) with the Expression between slash two and three. The trailing g stands for global, i.e, do this for every match of the RegEx in the current line. Without the g it would just stop processing after the first match. The RegEx itself is matching any non-capital letter and then those letters are replaced with nothing, i.e., effectively deleted.
You can use awk:
echo "Hello Guys!" | awk '{ gsub(/[^A-Z]/,"", $0); print;}'
HG
Also with tr:
echo "Hello Guys!" | tr -cd [:upper:]
HG
Also with sed :
echo "Hello Guys!" | sed 's/[^\[:upper:]]//g'
HG
You just need to remove the newline characters. You can use tr for that:
echo "HEllo Guys!" |grep -Eo '[A-Z]' |tr -d '\n'
HEG
Though, it cuts the last newline too.
You can use perl instead of grep
echo 'HEllo Guys!' | perl -lne 'print /([A-Z])/g'
HEG

How to search through a string and extract the required value in unix

I have a string like below
QUERY_RESULT='88371087|COB-A#2014-04-22,COB-C#2014-04-22,2014-04-22,2014-04-23 88354188|COB-W#2014-04-22,2014-04-22,2014-04-22 88319898|COB-X#2014-04-22,COB-K#2014-04-22,2014-04-22,2014-04-22'
This is a result taken by querying the database. Now I want to take all the values before the pipe and separate it with coma. So the output needed is :
A='88371087,88354188,88319898'
The db values can be different every time, there can be just one value or 2 or more values
How do I do it.
Using awk
A=`echo $QUERY_RESULT | awk '{ nreg=split($0,reg);for(i=1;i<=nreg;i++){split(reg[i],fld,"|");printf("%s%s",(i==1?"":","),fld[1]);}}'`
echo $A
88371087,88354188,88319898
Using grep -oP
grep -oP '(^| )\K[^|]+' <<< "$QUERY_RESULT"
88371087
88354188
88319898
OR to get comma separated value:
A=$(grep -oP '(^| )\K[^|]+' <<< "$QUERY_RESULT"|sed '$!s/$/,/'|tr -d '\n')
echo "$A"
88371087,88354188,88319898
$ words=( $( grep -oP '\S+(?=\|)' <<< "$QUERY_RESULT") )
$ A=$(IFS=,; echo "${words[*]}")
$ echo "$A"
88371087,88354188,88319898
Bash only.
shopt -s extglob
result=${QUERY_RESULT//|+([^ ]) /,}
result=${result%|*}
echo "$result"
Output:
88371087,88354188,88319898

Using awk to modify output

I have a command that is giving me the output:
/home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611
I need the output to be:
ea66574ff0daad6d0406f67e4571ee08 counted-file.xml
The closest I got was:
$ echo /home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611 | awk '{ printf "%s", $1 }; END { printf "\n" }'
/home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08
I'm not familiar with awk but I believe this is the command I want to use, any one have any ideas?
Or just a sed oneliner:
echo /home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611 \
| sed -E 's/.*:(.*\.xml).*/\1/'
$ echo "/home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611" |
cut -d: -f2 |
cut -d. -f1-2
ea66574ff0daad6d0406f67e4571ee08 counted-file.xml
Note that this relies on the dot . being present as in counted-file.xml.
$ awk -F[:.] -v OFS="." '{print $2,$3}' <<< "/home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611"
ea66574ff0daad6d0406f67e4571ee08 counted-file.xml
not sure if this is ok for you:
sed 's/^.*:\(.*\)\.[^.]*$/\1/'
with your example:
kent$ echo "/home/konnor/md5sums:ea66574ff0daad6d0406f67e4571ee08 counted-file.xml.20131003-083611"|sed 's/^.*:\(.*\)\.[^.]*$/\1/'
ea66574ff0daad6d0406f67e4571ee08 counted-file.xml
this grep line works too:
grep -Po ':\K.*(?=\..*?$)'

Select first part of string

How do I pull a substring from a string. For example, from the string:
'/home/auto/gift/surprise'
take only:
'/home/auto/'
Note that '/home/auto/gift/surprise' may vary, i.e., instead of having 4 directory levels, it may go to 6 or 8, yet I'm only interested in the first 2 folders.
Here's what I've tried so far, without success:
$ pwd
'/home/auto/gift/surprise'
$ pwd | sed 's,^\(.*/\)\?\([^/]*\),\1,'
'/home/auto/gift/'
I think it is better to use cut for this:
$ echo "/home/auto/gift/surpris" | cut -d/ -f1-3
/home/auto
$ echo "/home/auto/gift/surpris/bla/bla" | cut -d/ -f1-3
/home/auto
Note that cut -d/ -f1-3 means: strip the string based on the delimiter /, then print from the 1st to the 3rd parts.
Or also awk:
$ echo "/home/auto/gift/surpris" | awk -F/ 'OFS="/" {print $1,$2,$3}'
/home/auto
$ echo "/home/auto/gift/surpris/bla/bla" | awk -F/ 'OFS="/" {print $1,$2,$3}'
/home/auto
You may use parameter substitution, which is POSIX defined:
$ s="/home/auto/gift/surprise"
$ echo ${s%/*/*}
/home/auto

Resources