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
}
Related
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]
}
how to group sequence of item into square brackets
for example
List of items
cat item.txt
sn01
sn02
sn03
sn05
sn07
sn08
Desired output
sn[01-03,05,07-08]
If your data is same as shown Input_file sample then following may help you in same.
awk 'FNR==1{line=$0} {sub(/[a-z]+/,"")} $0-val>1 && val1!=val{out=out?out "," val1"-"val:line"[" val1"-"val;val1=$0} $0-val>1 && val1==val{out=out?out "," val1:out "," val1;val1=$0} {if(FNR==1){sub(/[0-9]+/,"",line);val1=$0};val=$0}END{if(val1!=val){print out "," val1"-"val"]"} else {print out "," val"]"}}' Input_file
Adding non-one liner form of solution too.
awk '
FNR==1{
line=$0
}
{
sub(/[a-z]+/,"")
}
$0-val>1 && val1!=val{
out=out?out "," val1"-"val:line"[" val1"-"val;
val1=$0
}
$0-val>1 && val1==val{
out=out?out "," val1:out "," val1;
val1=$0
}
{
if(FNR==1){
sub(/[0-9]+/,"",line);
val1=$0
};
val=$0
}
END{
if(val1!=val){
print out "," val1"-"val"]"
}
else{
print out "," val"]"
}
}
' Input_file
Output will be as follows.
sn[01-03,05,07-08]
"sn" being static here. it should pick it from the input file. when I
given list of items start with "cn". still it picks "sn"
Using awk:
$ cat infile
sn01
sn02
sn03
sn05
sn07
sn08
cn08
cn09
cn10
cn11
cn15
when search='sn'
$ awk -v search='sn' 'function pr(){if(f && l)printf("%s%s",n?",":search"[",f==l?f:f"-"l)}$0!~"^"search{next}{t=$1;sub(/[^0-9]+/,"",t)}f==""{f=l=t;next}t==l+1{l=t;next}{pr();f=l=t;n++}END{pr(); print n?"]":"Nothing matched for keyword :"search}' infile
sn[01-03,05,07-08]
when search='cn'
$ awk -v search='cn' 'function pr(){if(f && l)printf("%s%s",n?",":search"[",f==l?f:f"-"l)}$0!~"^"search{next}{t=$1;sub(/[^0-9]+/,"",t)}f==""{f=l=t;next}t==l+1{l=t;next}{pr();f=l=t;n++}END{pr(); print n?"]":"Nothing matched for keyword :"search}' infile
cn[08-11,15]
Better Readable :
awk -v search='sn' '
function pr()
{
if(f && l)
printf("%s%s",n?",":search"[",f==l?f:f"-"l)
}
$0!~"^"search{
next
}
{
t=$1;
sub(/[^0-9]+/,"",t)
}
f==""{
f=l=t;
next
}
t==l+1{
l=t;
next
}
{
pr();
f=l=t;
n++
}
END{
pr();
print n?"]":"Nothing matched for keyword :"search
}' infile
a simple awk solution
We're aiming to set LB and UB for each possible range.
Starting from LB, the last number in sequence upto which the common difference is 1 gives us the UB.
If difference is more than 1 print the last range and set LB again.
$ awk 'FNR==1{ $1=$1; prefix=substr($0,1,2);} {gsub(/[^0-9]/,"",$1); a[++i]=$1;} END{ printf prefix"["; LB=UB=prev=a[1]; for(i=1; i<=NR; i++){ if(int(a[i+1])==int(prev+1)) { UB=a[i+1]; prev=UB; } else { if(LB==UB) { printf LB"," } else {delim=(i==NR)? "]" :","; printf LB "-" UB delim; } prev=LB=UB=a[i+1]; }} }' file
sn[01-03,05,07-08]
gsub(/[^0-9]/,"",$1) : This sets all non-digit chars to null. Therefore $1 ends up with just numbers;
To understand it better :
$ awk 'FNR==1{ $1=$1; prefix=substr($0,1,2); } {gsub(/[^0-9]/,"",$1); a[++i]=$1;}
END
{
printf prefix"["; LB=UB=prev=a[1];
for(i=1; i<=NR; i++)
{
if(int(a[i+1])==int(prev+1))
{
UB=a[i+1];
prev=UB; }
else
{
if(LB==UB)
{
printf LB","
}
else
{
delim=(i==NR)? "]" :",";
printf LB "-" UB delim;
}
prev=LB=UB=a[i+1];
}
}
}' file
Awk solution:
awk '{ v=substr($0,3) }NR==1{ pfx=substr($0,1,2); r=a=v; next }
{ diff=v-a; if(diff>1) { r=r ((a==last)? ",":"-"a",")v; last=v } a=v }
END{ if(diff==1) r=r"-"v; print pfx"["r"]" }' file
The output:
sn[01-03,05,07-08]
This is my script:
for i in *.locs
do
awk -v start=$(head -n 1 ${i}) -v end=$(tail -n 1 ${i})
BEGIN {
sum = 0;
count = 0;
range_start = -1;
range_end = -1;
}
{
irow = int($1)
ival = $2 + 0.0
if (irow >= start && end >= irow) {
if (range_start == -1) {
range_start = NR;
}
sum = sum + ival;
count++;
}
else if (irow > end) {
if (range_end == -1) {
range_end = NR - 1;
}
}
}
END {
echo "${i}"
print "start =", range_start, "end =", range_end, "mean =", sum / count
}
done
Which gives me this error:
line 15: syntax error near unexpected token `}'
line 15: `}'
But when I first use the awk to generate the variables start and end followed by -f myscript.sh file
I don't get an error:
What am I missing?
Thanks in advance
You need to either quote the entire awk script, or escape the dollar signs so that the shell does not expand them as positional parameters before awk is called. (Adding single quotes takes care of the other problem, which is that without a line continuation character, the awk command itself ends at the end of the line and the rest of the script is parsed as incorrect bash code):
awk -v start=$(head -n 1 ${i}) -v end=$(tail -n 1 ${i}) '
BEGIN {
...
'
Characters within your awk program are being interpreted by the shell. You can pass your program as a command-line argument to awk, but it must be enclosed in 'single-quotes' to prevent the shell from interpreting it.
I have the following script:
script.sh:
#!/bin/bash
FileName=$1;
awk '
/Import()/
{
while (sub(/\$requestedMessage/, "bar") == 0)
{
print;
getline;
}
}
1' > file.tmp $FileName
And the following file:
file:
function FunctionA()
{
message=$requestedMessage
}
function FunctionB()
{
message=$requestedMessage
}
The idea is to call
./script.sh file
and to replace the message=$requestedMessage variable in function FunctionB() to message=bar but only in FunctionB() and not FunctionA()
I am very new to AWK and I don't seem to understand what I am doing wrong.
Thanks,
awk -v RS= -v ORS='\n\n' '
/FunctionB\(\)/ {
sub(/\$requestedMessage/, "bar")
}
1' "$FileName" > file
Maybe this is more like what you had in mind:
awk '
/^function/ { inTarget = (/FunctionB\(\)/ ? 1 : 0) }
inTarget { sub(/\$requestedMessage/, "bar") }
1' "$FileName" > file
If not - how do you know when you reach the end of a function definition? The above assumes you know one function has ended when the next function definition begins.