How to print all columns but last 2? - shell

How to print all columns but last 2?
e.g
input :echo FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008
output : FB_SYS_0032_I03_LTO3_idaen02r_02
delimiter : _ (underscore)

for your example, this awk one liner should do:
awk -F'_' -v OFS='_' 'NF-=2' file
test:
kent$  awk -F'_' -v OFS='_' 'NF-=2' <<< "FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008"
FB_SYS_0032_I03_LTO3_idaen02r_02

Just use an RE that describes the last 2 fields:
awk '{sub(/_[^_]*_[^_]*$/,"")}1'
or:
sed 's/_[^_]*_[^_]*$//'
e.g.:
$ echo FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008 | awk '{sub(/_[^_]*_[^_]*$/,"")}1'
FB_SYS_0032_I03_LTO3_idaen02r_02
$ echo FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008 | sed 's/_[^_]*_[^_]*$//'
FB_SYS_0032_I03_LTO3_idaen02r_02
Te above will work with any modern awk and any sed on any system.

use this awk command:
awk -F "_" '{for (i=1; i<=NF-2; i++) {printf ("%s", $i); if (i<NF-2) printf "_"} print ""}'
FB_SYS_0032_I03_LTO3_idaen02r_02

Using sed:
sed -r 's/(_[^_]*){2}$//'
For example,
$ echo 1_2_3_4_5 | sed -r 's/(_[^_]*){2}$//'
1_2_3
$ echo 1_2_3_4 | sed -r 's/(_[^_]*){2}$//'
1_2
$ echo FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008 | sed -r 's/(_[^_]*){2}$//'
FB_SYS_0032_I03_LTO3_idaen02r_02

Probably this is the simplest way:
$ input="FB_SYS_0032_I03_LTO3_idaen02r_02_20130820_181008"
$ echo "${input%_*_*}"
FB_SYS_0032_I03_LTO3_idaen02r_02

Related

Get only numbers in output

I need to get only numbers from this:
release/M_0.1.0
thus, need to extract with bash to have in output this:
0.1.0.
I have tried this but cannot finish it:
echo "release/M_0.1.0" | awk -F'/' '{print $2}'
And what about if given such string? relea234se/sdf23_4Mm0.1.0.8. How to get only 0.1.0.8? Please pay attention that this can be random digits such as 0.2 or 1.9.1.
Please check if this grep command works
echo "release/M_0.1.0" | egrep -o '[0-9.]+'
You could also use general parameter expansion parsing to literally remove characters up through the last that isn't digits or dots.
$: ver() { echo "${1//*[^.0-9]/}"; }
$: ver release/M_0.1.0
0.1.0
$: ver relea234se/sdf23_4Mm0.1.0.8
0.1.0.8
With sed you can do:
echo "release/M_0.1.0" | sed 's#.*_##'
Output:
0.1.0
Considering that your Input_file will be same as shown samples.
echo "$var" | awk -F'_' '{print $2}'
OR could use sub:
echo "$var" | awk '{sub(/.*_/,"")} 1'
With simple bash you could use:
echo "${var#*_}"
echo release/M_0.1.0 | awk -F\_ '{print $2}'
0.1.0
Take your pick:
$ var='relea234se/sdf23_4Mm0.1.0.8'
$ [[ $var =~ .*[^0-9.](.*) ]] && echo "${BASH_REMATCH[1]}"
0.1.0.8
$ echo "$var" | sed 's/.*[^0-9.]//'
0.1.0.8
$ echo "$var" | awk -F'[^0-9.]' '{print $NF}'
0.1.0.8
if data in d file, tried on gnu sed:
sed -E 's/relea.*/.*([0-9][0-9.]*)$/\1/' d

awk script read line matching a pattern and result output with comma separated

help with shell script to read pattern in comma separated line and end result output should again be in comma separated. In below eg, read line separated by commas and output only puppet strings again separated by commas.
echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" | script
output required:
docker-one,docker-three
awk to the rescue!
echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk 'BEGIN{RS=ORS=","} /puppet/'
puppet-one,puppet-two,puppet-four
for docker, and replacing the last comma
echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk 'BEGIN{RS=ORS=","} /docker/' |
sed 's/,$/\n/'
docker-one,docker-three
or, if you meant non puppet
echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk 'BEGIN{RS=ORS=","} !/puppet/' |
sed 's/,$/\n/'
docker-one,docker-three
It sounds like one of these might be what you're looking for:
$ echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk -F, '{for (i=1;i<=NF;i++) if ($i ~ /puppet/) printf "%s%s", (c++?FS:""), $i; print ""}'
puppet-one,puppet-two,puppet-four
$ echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk -F, '{for (i=1;i<=NF;i++) if ($i !~ /puppet/) printf "%s%s", (c++?FS:""), $i; print ""}'
docker-one,docker-three
$ echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" |
awk -F, '{for (i=1;i<=NF;i++) if ($i ~ /docker/) printf "%s%s", (c++?FS:""), $i; print ""}'
docker-one,docker-three
Using native bash regEx operator ~ and using GNU paste for csv formatting alone,
IFS="," read -ra myArray <<<"docker-one,puppet-one,puppet-two,docker-three,puppet-four"
for i in "${myArray[#]}";do [[ $i =~ ^puppet ]] && echo "$i" ; done | paste -sd ','
produces an output as
puppet-one,puppet-two,puppet-four
and for the other strings than the ones starting with puppet, do a negative regex match,
for i in "${myArray[#]}";do [[ ! $i =~ ^puppet ]] && echo "$i" ; done | paste -sd ','
docker-one,docker-three
Using tr, grep, and paste:
$ echo "docker-one,puppet-one,puppet-two,docker-three,puppet-four" \
| tr , '\n' | grep -v puppet | paste -s -d , -
docker-one,docker-three

Print only the contents after a certain pattern match

I have a string like this:
query:schema:query_result{cell=ab}: <timestamp>
I'd like to just print the ab and assign it to a variable. How can I do this with grep/sed?
You may try his,
$ var=$(grep -oP '=\K\w+' <<< "$str")
or
$ sed 's/.*=\(\w\+\).*/\1/' <<<"$var"
ab
You can also use awk:
s='query:schema:query_result{cell=ab}: <timestamp>'
awk -F '[=}]' '{print $2}' <<< "$s"
ab
To assign it to a variable:
var="$(awk -F '[=}]' '{print $2}' <<< "$s")"

shortening headers using awk

I have headers like
>XX|6226515|new|xx_000000.1| XXXXXXX
in a text file which I am trying shorten to
>XX6226515
using awk. I tried
awk -F"|" '/>/{$0=">"$1}1' input.txt > output.txt
but it yields the following instead
>XX|6226515|new|
awk -F"|" '{print $1$2}' input.txt > output.txt
Output:
>XX6226515
sed solution:
sed -e 's/|//' -e 's/|.*//'
The first substitution removes the first vertical bar, the second one removes the second one and anything after it.
$ awk -F'|' '$0=$1$2' <<< ">XX|6226515|new|xx_000000.1| XXXXXXX"
>XX6226515
This cut can also make it:
cut -d"|" --output-delimiter="" -f-2
See output:
$ echo ">XX|6226515|new|xx_000000.1| XXXXXXX" | cut -d"|" --output-delimiter="" -f-2
>XX6226515
-d"|" sets | as field delimiter.
--output-delimiter="" indicates that the output delimiter has to be empty.
-f-2 indicates that it has to print all records up to the 2nd (inclusive).
Also with just bash:
while IFS="|" read a b _
do
echo "$a$b"
done <<< ">XX|6226515|new|xx_000000.1| XXXXXXX"
See output:
$ while IFS="|" read a b _; do echo "$a$b"; done <<< ">XX|6226515|new|xx_000000.1| XXXXXXX"
>XX6226515

get the file name from the path

I have a file file.txt having the following structure:-
./a/b/c/sdsd.c
./sdf/sdf/wer/saf/poi.c
./asd/wer/asdf/kljl.c
./wer/asdfo/wer/asf/asdf/hj.c
How can I get only the c file names from the path.
i.e., my output will be
sdsd.c
poi.c
kljl.c
hj.c
You can do this simpy with using awk.
set field seperator FS="/" and $NF will print the last field of every record.
awk 'BEGIN{FS="/"} {print $NF}' file.txt
or
awk -F/ '{print $NF}' file.txt
Or, you can do with cut and unix command rev like this
rev file.txt | cut -d '/' -f1 | rev
You can use basename command:
basename /a/b/c/sdsd.c
will give you sdsd.c
For a list of files in file.txt, this will do:
while IFS= read -r line; do basename "$line"; done < file.txt
Using sed:
$ sed 's|.*/||g' file
sdsd.c
poi.c
kljl.c
hj.c
The most simple one ($NF is the last column of current line):
awk -F/ '{print $NF}' file.txt
or using bash & parameter expansion:
while read file; do echo "${file##*/}"; done < file.txt
or bash with basename :
while read file; do basename "$file"; done < file.txt
OUTPUT
sdsd.c
poi.c
kljl.c
hj.c
Perl solution:
perl -F/ -ane 'print $F[#F-1]' your_file
Also you can use sed:
sed 's/.*[/]//g' your_file

Resources