I am working with the zone.tab under /usr/share/zoneinfo/zonetab and I am having trouble displaying the data in a certain format.
the command I run:
cat zone.tab | awk '!/#/ {print $3}' | sort
this returns a list of regions and contries:
America/Washington
Pacific/Enderbury
What I need is for the above to return everything after the last / on each line.
There are some cases such as Pacific/Somewhere/A. I have a regex ([^/]+$) that should work but it doesn't. Any ideas?
You can also do it all in a single awk command:
awk '!/^#/ { sub(".*/", "", $3); print $3 }' /usr/share/zoneinfo/zone.tab
---- ----------------- --------
| | |
for non-comment lines | |
| |
modify 3rd col |
leaving only text |
after last slash |
|
Then print modified 3rd col
Pipe the output to sed -e 's;^.*/;;'. For example,
echo -e "America/Washington\nPacific/Enderbury" | sed 's;^.*/;;'
sed s:.*/:: /usr/share/zoneinfo/zone.tab
awk '!/^#/ { print $3;} ' < /usr/share/zoneinfo/zone.tab | awk -F/ ' { print $NF; }'
This regex might work:
# echo -e "a\n\a/b\na/b/c\na/b/c/d\n" |sed 's#^\(\([^/]*/\)*\)\(.*\)#\3#'
a
b
c
d
Perhaps sed -r 's#^(([^/]*/)*)(.*)#\3#' which removes the tangle of backslashes is clearer.
Related
Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 is my string and the result I want is vm-1.0.3
What is the best way to do this
Below is what I tried
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | awk -F - {'print $1,$2'}
vm 1.0.3
I also tried
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | awk -F - {'print $1"-",$2'}
vm- 1.0.3
Here I do not need space in between
I tried using cut and I got the expected result
$ echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F _ {'print $2'} | cut -c 1-8
vm-1.0.3
What is the best way to do the same?
Making assumptions from the 1 example you provided about what the general form of your input will be so it can handle that robustly, using any sed:
$ echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' |
sed 's/^[^-]*-[^-]*-[^_]*_\(.*\)-[^-]*$/\1/'
vm-1.0.3
or any awk:
$ echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' |
awk 'sub(/^[^-]+-[^-]+-[^_]+_/,"") && sub(/-[^-]+$/,"")'
vm-1.0.3
You don't need 2 calls to awk, but your syntax with the single quotes outside the curly's, including printing the hyphen:
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 |
awk -F_ '{print $2}' | awk -F- '{print $1 "-" $2}'
If your string has the same format, let the field separator be either - or _
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F"[-_]" '{print $4 "-" $5}'
Or split the second field on - and print the first 2 parts
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 | awk -F_ '{
split($2,a,"-")
print a[1] "-" a[2]
}'
Or with gnu-awk a bit more specific match with a capture group:
echo Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2 |
awk 'match($0, /^Apps-[^_]*_(vm-[0-9]+\.[0-9]+\.[0-9]+)/, a) {print a[1]}'
Output
vm-1.0.3
This is the easiest I can think of:
echo "Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2" | cut -c 25-32
Obviously you need to be sure about the location of your characters. In top of that, you seem to be have two separators: '_' and '-', while both characters also are part of the name of your entry.
echo 'Apps-10.00.00R000-B1111_vm-1.0.3-x86_64.qcow2' | sed -E 's/^.*_vm-([0-9]+).([0-9]+).([0-9]+)-.*/vm-\1.\2.\3/'
After executing this
ta=`zcat abc.log.2019071814.gz |grep "R_MT"|grep "A:1234"|grep "ID:413"|awk -F"|" '{print $20}'|sort|uniq -c|awk '{$1=$1};1'`
Here $20 indicates the "S:" entry in each row (I am taking the unique count of all s values),I am getting result as
93070 S:1 11666 S:8 230 S:9
so what I need is the sum of all occurrence of s values .i.e 93070+11666+230
so result be total=104966
$ echo 93070 S:1 11666 S:8 230 S:9 | sed -E 's,S:[0-9]+,,g' | sed 's, ,+,g' | bc -
104966
Append to your last awk:
| awk '{sum+=$1} END {print sum}'
or use this (awk ignores columns with S:1, S:8 and S:9):
echo $ta | awk '{for(i=1;i<=NF;i++) t+=$i; print t; t=0}'
or use every second column:
echo $ta | awk '{for(i=1;i<=NF;i=i+2) t+=$i; print t; t=0}'
I won't help you all the way, but know that you can use bc to perform arithmetic.
echo "93070 + 11666 + 230" | bc
would give you:
104966
I'm trying to make part of the output of the first command as another command's argument.
Output of first command is like this, and 3000 is what I want:
XXXXXXXXXXXXX
abcdefg 1020 10:30
[1000] 3000
I extract the pattern by ./command1 | grep '^\[' | awk 'print $2', so it will print out 3000, the value I want.
I'd like to make 3000 as an argument of command2 ./command2 3000. How do I make this work?
command2 $( command1 | awk '/\[/{ print $2 }' )
You can use xargs to pass the input to a new command. In your example you need to include curly braces in your awk argument as well.
./command1 | grep '^\[' | awk '{ print $2 } ' | xargs ./command2
Or more concisely
.command1 | awk '/^\[/ { print $2 }' | xargs ./command2
Example:
echo "[1000] 3000" | awk '/^\[/ { print $2 }' | xargs echo
Output:
3000
There's also sed:
./command1 | sed -n 'n;n;p' | awk '{print $2}'
All together now:
./command2 $(./command1 | sed -n 'n;n;p' | awk '{print $2}') # ./command2 3000
sed will skip 2 lines and print the third.
I would personally try backticks first:
./command2 `./command1 | grep '^\[' | awk 'print $2'`
For example suppose I wish for a CSV file with 5 columns. How could I convert
a,b,c,d
d,e,f
into
a,b,c,d,
d,e,f,,
Easy in Awk:
awk -F, -vOFS=, '{$5=$5}1'
Not too hard in Bash:
IFS=,
while read -a F; do
for ((i=0; i<5; i++)); do
F[i]=${F[i]}
done
echo "${F[*]}"
done
Example with awk:
$ awk -F, '{printf("%s,%s,%s,%s,%s\n",$1,$2,$3,$4,$5)}' example.txt
a,b,c,d,
d,e,f,,
or
$ awk -F, -v OFS=, '{print $1,$2,$3,$4,$5}' example.txt
I found a solution with GNU sed:
sed -r 's/^([^,]*)(,|)([^,]*)(,|)([^,]*)(,|)([^,]*)(,|)$/\1,\3,\5,\7,/'
# | | | | ^ ^ ^ ^
# | | | | | | | |
# |__________|__________|__________|__________| | | |
# |__________|__________|_____________| | |
# |__________|________________| |
# |___________________|
Proof:
echo -e "a,b,c,d\nd,e,f\nx" | sed -r 's/^([^,]*)(,|)([^,]*)(,|)([^,]*)(,|)([^,]*)(,|)$/\1,\3,\5,\7,/'
a,b,c,d,
d,e,f,,
x,,,,
Another approach which I like very much is this:
gawk '{print $0 ",,,,,"}' a | cut -d \, -f 1-5
I think it is much more simple and clear
cat t.incopt.02.20110221 | awk -F, '{print $1}' | sort | uniq
got unque records
but if i inserted into perl,
#FETCH_REQ_DETAILS = `cat t.incopt.02.20110221 | awk -F\, '{print $1}' \| sort \| uniq`;
if i print the above array vari, i getting entire file content, i guess the linux command not working correctly when i use inside perl,
I think you just need to enclose the command in back tick and escape only the $
#FETCH_REQ_DETAILS = `cat t.incopt.02.20110221 | awk -F, '{print \$1}' | sort | uniq;`
Try the following:
my $cmd='cat t.incopt.02.20110221 | awk -F, \'{print $1}\' | sort | uniq';
#FETCH_REQ_DETAILS = `$cmd`;