I would like to combine these 2 commands :
COMMAND 1:
`BEGIN {
ip = ARGV[2]
split(ip, octets, ".")
for (i = 1; i <= 4; i++) {
dec += octets[i] * 256 ** (4 - i)
}
printf("%i\n", dec)
}`
COMMAND 2:
`BEGIN{
FS=",";
}
{
if ($4 == dec){
print $7;
}
}
END {
print "END";
}`
FILE TO READ:
"16777216","16777471","apnic","1313020800","AU","AUS","Australia"
"16777472","16777727","apnic","1302739200","CN","CHN","China"
"16777728","16778239","apnic","1302739200","CN","CHN","China"
"16778240","16779263","apnic","1302566400","AU","AUS","Australia"
"16779264","16781311","apnic","1302566400","CN","CHN","China"
The first command is used to convert an IPV4 address into decimal and the second one is used to search the decimal in a .csv file.
Therefore, I would like to use a command like the following one:
awk -f script.awk fileToRead.csv 10101100.00010000.11111110.00000001
Concatenating your 2 files would just about do what you want (after zapping ARGV[2] so it's not treated as a file):
BEGIN {
ip = ARGV[2]
split(ip, octets, ".")
for (i = 1; i <= 4; i++) {
dec += octets[i] * 256 ** (4 - i)
}
ARGV[2] = ""
ARGC--
}
BEGIN{
FS=",";
}
{
if ($4 == dec){
print $7;
}
}
END {
print "END";
}
but I'd recommend you rewrite it as:
BEGIN {
split(ip, octets, /[.]/)
for (i = 1; i <= 4; i++) {
dec += octets[i] * 256 ** (4 - i)
}
FS=","
}
$4 == dec {
print $7
}
END {
print "END"
}
and then call it as:
awk -v 10101100.00010000.11111110.00000001 -f script.awk fileToRead.csv
just to tidy it up a bit.
Related
I want to use this table:
a 16 moe max us
b 11 tom mic us
d 14 roe fox au
t 29 ann teo au
n 28 joe joe ca
and make this matrix by using awk (or any other simple option in bash):
a_16; b_11; d_14; t_29; n_28
us; moe_max; tom_mic; ; ;
au; ; ; roe_fox; ann_teo;
ca; ; ; ; ; joe_joe
I tried this but it didn't work:
awk '{a[$5]=a[$5]?a[$5] FS $1"_"$2:$1"_"$2; b[$5]=b[$5]?b[$5] FS $3"_"$4:$3"_"$4;} END{for (i in a){print i"\t" a[i] "\t" b[i];}}' fis.txt
Using any awk
$ cat tst.awk
{
row = $NF
col = $1 "_" $2
vals[row,col] = $3 "_" $4
}
!seenRow[row]++ { rows[++numRows] = row }
!seenCol[col]++ { cols[++numCols] = col }
END {
OFS = "; "
printf " "
for ( colNr=1; colNr<=numCols; colNr++ ) {
col = cols[colNr]
printf "%s%s", col, (colNr<numCols ? OFS : ORS)
}
for ( rowNr=1; rowNr<=numRows; rowNr++ ) {
row = rows[rowNr]
printf "%s%s", row, OFS
for ( colNr=1; colNr<=numCols; colNr++ ) {
col = cols[colNr]
#val = ((row,col) in vals ? vals[row,col] : " ")
val = vals[row,col]
printf "%s%s", val, (colNr<numCols ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
a_16; b_11; d_14; t_29; n_28
us; moe_max; tom_mic; ; ;
au; ; ; roe_fox; ann_teo;
ca; ; ; ; ; joe_joe
I can't see the pattern in the expected output in your question of when there should be 1, 2, 3, or 4 spaces after each ; so I just used a consistent 2 in the above. Massage it to suit.
Using gawk multidimensional arrays for collecting header columns and row indices:
awk '{
head[NR] = $1"_"$2;
idx[$5][NR] = $3"_"$4
}
END {
h = ""; col_size = length(head);
for (i = 1; i <= col_size; i++) {
h = sprintf("%s %s", h, head[i])
}
print h;
for (lab in idx) {
printf("%s", lab);
for (i = 1; i <= col_size; i++) {
v = sprintf("%s; %s", v, idx[lab][i])
}
print v;
v = "";
}
}' test.txt
a_16 b_11 d_14 t_29 n_28
ca; ; ; ; ; joe_joe
au; ; ; roe_fox; ann_teo;
us; moe_max; tom_mic; ; ;
Here is a ruby to do that:
ruby -e 'd=$<.read.
split(/\R/).
map(&:split).
map{|sa| sa.each_slice(2).map{|ss| ss.join("_") } }.
group_by{|sa| sa[-1] }
# {"us"=>[["a_16", "moe_max", "us"], ["b_11", "tom_mic", "us"]], "au"=>[["d_14", "roe_fox", "au"], ["t_29", "ann_teo", "au"]], "ca"=>[["n_28", "joe_joe", "ca"]]}
heads=d.values.flatten(1).map{|sa| sa[0]}
# ["a_16", "b_11", "d_14", "t_29", "n_28"]
hsh=Hash.new {|h,k| h[k] = ["\t"]*heads.length}
d.each{|k,v|
v.each{|sa|
hsh[k][heads.index(sa[0])]="\t#{sa[1]}"
}
}
puts heads.map{|e| "\t#{e}" }.join(";")
hsh.each{|k,v| puts "#{k};\t#{v.join(";")}"}
' file
Prints:
a_16; b_11; d_14; t_29; n_28
us; moe_max; tom_mic; ; ;
au; ; ; roe_fox; ann_teo;
ca; ; ; ; ; joe_joe
How can I check if ranges overlap other ranges and combine the ones that do?
Example:
10-1000,15-350,50-1500,2100,1700-1800,45,40,145,2-1300
The result I want is:
2-1500,1700-1800,2100
I tried to make a plan on how to code it but it's getting me nowhere. Is there a useful package that I can use? Or if not what should my approach be?
Using sort and awk:
tr , '\n' | sort -n | awk '
BEGIN {
FS = OFS = "-"
}
NF == 1 {
$2 = $1
}
$2 <= end {
next
}
$1 <= end {
end = $2
next
}
{
emit()
start = $1
end = $2
}
END {
emit()
}
function emit() {
if (NR != 1) {
if (start == end)
print start
else
print start, end
}
}' | paste -sd,
$ sh ./merge.sh <<<10-1000,15-350,50-1500,2100,1700-1800,45,40,145,2-1300
2-1500,1700-1800,2100
I have a file as following format
Item-abc,c1,300
Item-abc,c2,500
Item-pqr,c1,900
Item-pqr,c2,800
Item-pqr,c3,600
Item-pqr,c4,700
Item-xyz,c1,950
Item-asd,
Item-jkl
I need this file rearranged in following manner
Item-abc,c1=300,c2=500
Item-pqr,c1=900,c2=800,c3=600,c4=700
Item-xyz,c1=950
If second and third columns are empty then that line should ve removed completely
$ cat tst.awk
BEGIN { FS=OFS="," }
$1 != prev { if (NR>2) print rec; rec=prev=$1 }
{ rec = rec OFS $2 "=" $3 }
END { print rec }
$ awk -f tst.awk file
Item-abc,c1=300,c2=500
Item-pqr,c1=900,c2=800,c3=600
cat answer.awk
BEGIN {
FS=","
RS="\r\n" # For Windows"
}
{
N[$1,$2]= $3
}
END {
for (comb in N) {
split (comb,S,SUBSEP)
K[S[1]]=K[S[1]] "," S[2] "=" N[S[1],S[2]]
}
for (j in K) if (j != "Name") print j K[j]
}
awk -f answer.awk file
Item-abc,c1=300,c2=500
Item-pqr,c1=900,c2=800,c3=600
#Jerin, this variant will strip \r'ss
BEGIN {
FS=","
}
{
sub(/\x0d/,"",$0)
split($0,Cols)
N[Cols[1],Cols[2]]= Cols[3]
}
END {
for (comb in N) {
split (comb,S,SUBSEP)
K[S[1]]=K[S[1]] "," S[2] "=" N[S[1],S[2]]
}
for (j in K) if (j != "Name") print j K[j]
}
Input :
name;surname;street;profession;sex;age;city
name1;surname1;street1;prof1;male;22;city1
name2;surname2;street2;prof2;male;25;city2
name1;surname1;street1;prof1;male;23;city3
Data is stored in *.csv file, the goal is count average of age for each profession. So, expected output is:
avg of prof1 = 22,5
avg of prof2 = 25
awk to the rescue!
$ awk -F';' 'NR>1 {k=$4; sum[k]+=$6; count[k]++}
END {for(k in sum) print "avg of " k " = " sum[k]/count[k]}' file
avg of prof1 = 22.5
avg of prof2 = 25
$ cat age.awk
BEGIN {
FS = ";"
}
NR == 1 {
for (i = 1; i <= NF; i++) { # where are profession and age?
if ($(i) == "profession") pro_id = i
if ($(i) == "age") age_id = i
}
next
}
{
pro = $(pro_id)
age = $(age_id)
av[pro] += age
n[pro] ++
}
END {
for (pro in av) av[pro] /= n[pro]
for (pro in av)
printf "avg of %s = %s\n", pro, av[pro] | "sort"
}
Usage:
$ awk -f age.awk file.csv
My code 1 :
awk -F'|' -v PARM_VAL="${PARM_VALUE[*]}" '
BEGIN { split(PARM_VAL,pa," ")
fn_1()
{
print "inside fn"
}
}
FNR==NR{ for(i=1;i<=NF;i++) a[NR,i]=$i; }
{if (FILENAME == "SPP_OUT") {print $1}}
fn_1
END {printf " second value of SPPIN : "a[2,2]} ' SPP_IN SPP_OUT
I am getting error fatal: function `fn_1' not defined
My code 2 :
awk -F'|' -v PARM_VAL="${PARM_VALUE[*]}" '
BEGIN { split(PARM_VAL,pa," ")
fn_1()
{
ret = "returned"
return ret
}
}
FNR==NR{ for(i=1;i<=NF;i++) a[NR,i]=$i; }
{if (FILENAME == "SPP_OUT") {print $1}}
m=fn_1()
END {printf " second value of SPPIN : "a[2,2];print $m} ' SPP_IN SPP_OUT
I am facing
awk: cmd. line:6: return ret
awk: cmd. line:6: ^ `return' used outside function context
Can any asssist ?
Thanks
The function should be defined out of the BEGIN block. For example:
$ cat function.awk
function fib(n, n_1, n_2)
{
if (n < 2) {
return n
} else {
n_1 = fib(n - 1)
n_2 = fib(n - 2)
return n_1 + n_2
}
}
BEGIN {
for (i = 0; i < 5; ++i) {
printf("fib(%d) = %d\n", i, fib(i));
}
}
$ awk -f function.awk
fib(0) = 0
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
$
The user-defined awk function syntax is
function NAME(PARAMETER-LIST)
{
BODY-OF-FUNCTION
}
The tricky part is:
PARAMETER-LIST is a list of the function's arguments and local variable
names, separated by commas. When the function is called, the argument
names are used to hold the argument values given in the call. The
local variables are initialized to the empty string. A function cannot
have two parameters with the same name, nor may it have a parameter
with the same name as the function itself.
See the awk manual for more details.
To get the nucleus of your code working I had to add the function keyword when defining the function, and parentheses when making the call like so:
$ cat foo.awk
BEGIN { print "begin" }
function fn_1()
{
print "inside fn"
}
{
fn_1()
}
END { print "end" }
$ echo 'xyz' | awk -f foo.awk
begin
inside fn
end
From the awk manual:
The definition of a function named name looks like this:
function name(parameter-list)
{
body-of-function
}