awk To Generate Sequence Numbers based on Start and End Range: - awk

Would like to generate Generate Sequence Numbers based on Start and End Range along with description.
Input.txt
SatrtRange,EndRange,Date, Desc
5,10,20-Jun-2014,abc
20,25,30-Jun-2014,def
2,2,15-May-2014,ghi
Have tried below command and got partial output:
awk -F, '{s[NR]=$1;e[NR]=$2;} { for (i=s[NR];i<=e[NR];i++) print i} ' Input.txt >Op_Con_Seq_Num.txt
Output:
5
6
7
8
9
10
20
21
22
23
24
25
2
However, want to print other fields info as well from Input.txt , please suggest ..
Desired Output:
5,20-Jun-2014,abc
6,20-Jun-2014,abc
7,20-Jun-2014,abc
8,20-Jun-2014,abc
9,20-Jun-2014,abc
10,20-Jun-2014,abc
20,30-Jun-2014,def
21,30-Jun-2014,def
22,30-Jun-2014,def
23,30-Jun-2014,def
24,30-Jun-2014,def
25,30-Jun-2014,def
2,15-May-2014,ghi

awk 'BEGIN{FS=OFS=","} {for (i=$1;i<=$2;i++) print i,$3,$4}' Input.txt

You're very close:
awk -F, '{s[NR]=$1;e[NR]=$2;} { for (i=s[NR];i<=e[NR];i++) print i","$3","$4} ' Input.txt

Related

How to swap the last two column pairs with awk?

I am trying this
awk '{B=$(NF-1);A=$NF; $NF=$(NF-2); $(NF-1) = $(NF-3); $(NF-2)=A; $(NF-3) = B; print;}' input_text.txt
but I get the error:
awk: cmd. line:1: (FILENAME=cazzo.txt FNR=2) fatal: attempt to access field -1
Sample input:
$ cat input_text.txt
1 7 9 11 0 5 2
The same happens if I replace the spaces with tabs in the input_text.txt file.
Expected output:
1 7 9 5 2 11 0
I am running with Cygwin on Windows 10.
You can try this awk for swapping values:
awk 'NF > 3 {a=$NF; b=$(NF-1); $NF=$(NF-2); $(NF-1)=$(NF-3); $(NF-3)=b; $(NF-2)=a} 1' file
1 7 9 5 2 11 0
If there are DOS line breaks then use:
awk -v RS='\r?\n' 'NF > 3 {a=$NF; b=$(NF-1); $NF=$(NF-2); $(NF-1)=$(NF-3); $(NF-3)=b; $(NF-2)=a} 1' file
If you have gnu awk then you can use this regex based approach:
awk -v RS='\r?\n' 'NF > 3 {
$0 = gensub(/(\S+\s+\S+)(\s+)(\S+\s+\S+)$/, "\\3\\2\\1", "1")} 1' file
1 7 9 5 2 11 0
To swap the last n fields with the n fields before them:
$ awk -v n=2 'NF>=(2*n){ for (i=NF-(n-1); i<=NF; i++) {t=$i; $i=$(i-n); $(i-n)=t} } 1' file
1 7 9 5 2 11 0
$ awk -v n=3 'NF>=(2*n){ for (i=NF-(n-1); i<=NF; i++) {t=$i; $i=$(i-n); $(i-n)=t} } 1' file
1 0 5 2 7 9 11
With your shown samples, please try following code. This is a Generic code, where you have 2 awk variables named fromFields and toFields. So you need to give their values like: let's say you want to substitute 4th field value with 6th field AND 5th field value with 7th field, so you will set it like: fromFields="4,5" and toFields="6,7". I am assuming user will understand that values which are given are feasible with respect to Input_file.
awk -v fromFields="4,5" -v toFields="6,7" '
BEGIN{
num1=split(fromFields,arr1,",")
num2=split(toFields,arr2,",")
}
{
tmp=""
for(i=1;i<=num1;i++){
tmp=$arr1[i]
$arr1[i]=$arr2[i]
$arr2[i]=tmp
}
}
1
' Input_file

awk to add one to column based on condition

Trying to add a awk condition that will add one to $2 if the sum of $3 - $2is greater than one, The below has a syntax error on the if line. Thank you :).
file
2 21002880 21002881
17 3476163 3476186
11 108292759 108292760
2 218661210 218661265
2 21002865 21002866
desired
2 21002880 21002881
17 3476164 3476186
11 108292759 108292760
2 218661211 218661265
2 21002865 21002866
awk
awk 'BEGIN {FS=OFS="\t"} {sum+=$3-$2} # define FS, OFS, and sum
if((sum > 1)) { # condition check
print $1,$2+1,$3 # print desired output
next # goto next line
}
}1' file.txt
Another short one:
awk -v OFS="\t" '{$2+=($3-$2>1)}1' file
Output:
2 21002880 21002881
17 3476164 3476186
11 108292759 108292760
2 218661211 218661265
2 21002865 21002866
I missed a { and needed sum=$3-$2
awk 'BEGIN {FS=OFS="\t"} {sum=$3-$2} # define FS, OFS, and sum
{
if((sum > 1)) { # condition check
print $1,$2+1,$3 # print desired output
next # goto next line
}
}1' file.txt

How to add zeros to print according to number of digit in awk?

I have input:
12
2
3
56
and I would like to print a word with number in first column consisting from 5 numbers. How to add zeros before this number please?
awk '{print "file"$1".ASC}' input > output
The desired output:
file00012
file00002
file00003
file00056
$ awk '{printf "file%05d\n", $1}' infile.txt
file00012
file00002
file00003
file00056

Print every second consequtive field in two columns - awk

Assume the following file
#zvview.exe
#begin Present/3
77191.0000 189.320100 0 0 3 0111110 16 1
-8.072430+6-8.072430+6 77190 0 1 37111110 16 2
37 2 111110 16 3
8.115068+6 0.000000+0 8.500000+6 6.390560-2 9.000000+6 6.803440-1111110 16 4
9.500000+6 1.685009+0 1.000000+7 2.582780+0 1.050000+7 3.260540+0111110 16 5
37 2 111110 16 18
What I would like to do, is print in two columns, the fields after line 6. This can be done using NR. The tricky part is the following : Every second field, should go in one column as well as adding an E before the sign, so that the output file will look like this
8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0
From the output file you see that I want to keep in $6 only length($6)=10 characters.
How is it possible to do it in awk?
can do all in awk but perhaps easier with the unix toolset
$ sed -n '6,7p' file | cut -c2-66 | tr ' ' '\n' | pr -2ats' '
8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0
Here is a awk only solution or comparison
$ awk 'NR>=6 && NR<=7{$6=substr($6,1,10);
for(i=1;i<=6;i+=2) {f[++c]=$i;s[c]=$(i+1)}}
END{for(i=1;i<=c;i++) print f[i],s[i]}' file
8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0
Perhaps shorter version,
$ awk 'NR>=6 && NR<=7{$6=substr($6,1,10);
for(i=1;i<=6;i+=2) print $i FS $(i+1)}' file
8.115068+6 0.000000+0
8.500000+6 6.390560-2
9.000000+6 6.803440-1
9.500000+6 1.685009+0
1.000000+7 2.582780+0
1.050000+7 3.260540+0
to convert format to standard scientific notation, you can pipe the result to
sed or embed something similar in awk script (using gsub).
... | sed 's/[+-]/E&/g'
8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0
With GNU awk for FIELDWIDTHS:
$ cat tst.awk
BEGIN { FIELDWIDTHS="9 2 9 2 9 2 9 2 9 2 9 2" }
NR>5 && NR<8 {
for (i=1;i<NF;i+=4) {
print $i "E" $(i+1), $(i+2) "E" $(i+3)
}
}
$ awk -f tst.awk file
8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0
If you really want to get rid of the leading blanks then there's various ways to do it (simplest being gsub(/ /,"",$<field number>) on the relevant fields) but I left them in because the above allows your output to line up properly if/when your numbers start with a -, like they do on line 4 of your sample input.
If you don't have GNU awk, get it as you're missing a LOT of extremely useful functionality.
I tried to combine #karafka 's answer using substr, so the following does the trick!
awk 'NR>=6 && NR<=7{$6=substr($6,1,10);for(i=1;i<=6;i+=2) print substr($i,1,8) "E" substr($i,9) FS substr($(i+1),1,8) "E" substr($(i+1),9)}' file
and the output is
8.115068E+6 0.000000E+0
8.500000E+6 6.390560E-2
9.000000E+6 6.803440E-1
9.500000E+6 1.685009E+0
1.000000E+7 2.582780E+0
1.050000E+7 3.260540E+0

AWK: Divide any element of any row by some element of another row

I have got a text file with some structure like this:
2 2 4 5 6
1 9 7 6 2
1 5 2 8 5
I want to be able to divide any element of any row by an element of another row. For example if I wanted to divide the 3rd element of the 1st row by the 2nd element of the 3rd row that would give:
4/5 = 0.8
Couldn't figure out a smart way to do this with AWK. Suggestions?
This MAY be what you want but it's hard to tell without more details and the expected output:
$ awk -v num=1,5 -v den=3,3 '{for (i=1;i<=NF;i++) cell[NR","i]=$i} END{print (cell[den] ? cell[num]/cell[den] : "NaN")}' file
3
$ awk -v num=3,4 -v den=1,2 '{for (i=1;i<=NF;i++) cell[NR","i]=$i} END{print (cell[den] ? cell[num]/cell[den] : 0)}' file
4
If (i1, j1) and (i2, j2) are the coordinates of the numerator and the denominator, you can do this :
i1=1
j1=3
i2=3
j2=2
awk 'NR=='$i1'{a=$'$j1'} NR=='$i2' {b=$'$j2'} END {print a"/"b " = " a/b}' file