awk + export value to awk - awk

the following program needs to print the words
First
Second
Third
But because i parameter from awk not get the value from “for” loop its print all words:
First second third
First second third
First second third
How to fix awk in order to print first the “first” word second the “second” word and so on
THX
Yael
program:
for i in 1 2 3
do
echo "first second third" | awk '{print $i}'
done

You can change you code like this:
for i in 1 2 3
do
echo "first second third" | awk -v i=$i '{print $i}'
done
To use the variable 'i' from the shell.
You can also just change the record separator (RS) to have the same result :
echo "first second third" | awk 'BEGIN{RS=" "} {print $1}'
But I'm not sure if that's what you're looking for.

You could do:
for a in First Second Third
do
awk 'BEGIN { print ARGV[1] }' $a
done
Or you could do:
for a in First Second Third
do
awk -v arg=$a 'BEGIN { print arg }'
done

don't do the unnecessary. the shell for loop is not needed! Just do it with awk!
$ echo "first second third" | awk '{for(i=1;i<=NF;i++)print $i}'

Or you could use:
echo "first second third" | awk -F " " -v OFS="\n" '{print $1,$2,$3}'

Related

awk conditional statement based on a value between colon

I was just introduced to awk and I'm trying to retrieve rows from my file based on the value on column 10.
I need to filter the data based on the value of the third value if ":" was used as a separator in column 10 (last column).
Here is an example data in column 10. 0/1:1,9:10:15:337,0,15.
I was able to extract the third value using this command awk '{print $10}' file.txt | awk -F ":" '/1/ {print $3}'
This returns the value 10 but how can I return other rows (not just the value in column 10) if this third value is less than or greater than a specific number?
I tried this awk '{if($10 -F ":" "/1/ ($3<10))" print $0;}' file.txt but it returns a syntax error.
Thanks!
Your code:
awk '{print $10}' file.txt | awk -F ":" '/1/ {print $3}'
should be just 1 awk script:
awk '$10 ~ /1/ { split($10,f,/:/); print f[3] }' file.txt
but I'm not sure that code is doing what you think it does. If you want to print the 3rd value of all $10s that contain :s, as it sounds like from your text, that'd be:
awk 'split($10,f,/:/) > 1 { print f[3] }' file.txt
and to print the rows where that value is less than 7 would be:
awk '(split($10,f,/:/) > 1) && (f[3] < 7)' file.txt

Need to retrieve a value from an HL7 file using awk

In a Linux script program, I've got the following awk command for other purposes and to rename the file.
cat $edifile | awk -F\| '
{ OFS = "|"
print $0
} ' | tr -d "\012" > $newname.hl7
While this is happening, I'd like to grab the 5th field of the MSH segment and save it for later use in the script. Is this possible?
If no, how could I do it later or earlier on?
Example of the segment.
MSH|^~\&|business1|business2|/u/tmp/TR0049-GE-1.b64|routing|201811302126||ORU^R01|20181130212105810|D|2.3
What I want to do is retrieve the path and file name in MSH 5 and concatenate it to the end of the new file.
I've used this to capture the data but no luck. If fpth is getting set, there is no evidence of it and I don't have the right syntax for an echo within the awk phrase.
cat $edifile | awk -F\| '
{ OFS = "|"
{fpth=$(5)}
print $0
} ' | tr -d "\012" > $newname.hl7
any suggestions?
Thank you!
Try
filename=`awk -F'|' '{print $5}' $edifile | head -1`
You can skip the piping through head if the file is a single line
First of all, it must be mentioned that the awk line in your first piece of code, has zero use:
$ cat $edifile | awk -F\| ' { OFS = "|"; print $0 }' | tr -d "\012" > $newname.hl7
This is totally equivalent to
$ cat $edifile | tr -d "\012" > $newname.hl7
because OFS is only used to redefine $0 if you redefine a field.
Example:
$ echo "a|b|c" | awk -F\| '{OFS="/"; print $0}'
a|b|c
$ echo "a|b|c" | awk -F\| '{OFS="/"; $1=$1; print $0}'
a/b/c
I understand that you have a hl7 file in which you have a single line starting with the string "MSH". From this line you want to store the 5th field: this is achieved in the following way:
fpth=$(awk -v outputfile="${newname}.hl7" '
BEGIN{FS="|"; ORS="" }
($1 == "MSH"){ print $5 }
{ print $0 > outputfile }' $edifile)
I have replaced ORS to an empty character set, as it is equivalent to tr -d "\012". The above will work very nicely if you only have a single MSH in your file.

Awk splitting a string and comparison

I have a string like AS|REQ|XYZ|value=12 which I am splitting with:
awk -F\| 'print {$4}' | awk -F"=" '{print $2}'
This gives the value 12.
But for the string DF|REG|EXP|value=, it comes back blank.
What I need as if my string encounters value in fourth column and is blank, throw error. Can this be done in awk command ?
Thanks
#JamesBrown has the right answer to your question as asked, but given the input you posted all you need to produce the output you want is:
awk -F'=' '{print ($NF=="" ? "Error" : $NF)}' file
If that's NOT all you need then edit your question to show some more truly representative sample input and expected output.
You could be more specific about what you mean by throwing an error. If you want the program to exit with a non-zero exit code, use if and exit with value`:
$ awk 'BEGIN{exit}'
$ echo $?
0
$ awk 'BEGIN{exit 1}'
$ echo $?
1
$ awk -F\| '{split($4,a,"="); if(a[2]=="") exit 1; else print a[2]}' foo
12
$ echo $?
1
or just print an error message and continue execution:
$ awk -F\| '{split($4,a,"="); print (a[2]==""?"ERROR":a[2])}' foo
12
ERROR
Test data used above:
$ cat foo
AS|REQ|XYZ|value=12
DF|REG|EXP|value=
Something like this perhaps?
awk -F\| '{print $4}' | awk -F"=" '{if ($2 == "") print "ERROR: Empty Value"; else print $2}'
Hope this command might work for you. The below command will behave as expected. If you have any value in the value field, it will just print the value. Else if it is blank, it prints "error". The string was placed in test.txt
awk -F\| '{if($4!="value=") {gsub("value=","",$4);print $4} else print "error" }' test.txt
Something like this -
cat f
AS|REQ|XYZ|value=12
AS|REQ|XYZ|value=
awk -F'[|=]' '{if($4 == "value" && $5 == "") {print ("Error Found at Line: ",NR)} else {print $0}}' f
AS|REQ|XYZ|value=12
Error Found at Line: 2
It search for value in 4th column and blank in 5th column.

AWK: Apply filter only if field separator is present

I surprisingly found that when you do this:
echo "hello" | awk -F'|' '{print $1;}'
you get:
hello
How to return nothing given that the field separator '|' is absent in the line ?
I do this to extract dates in beginning of log lines, but some lines don't start with a date and then give me this problem. Thanks, I am quite new in awk.
You can do this
echo "hello" | awk -F'|' 'NF>1 {print $1}'
echo "hello|1" | awk -F'|' 'NF>1 {print $1}'
hello
Only when you have more than one field, return the first field
On a file
cat testing
record1|val1
record2|val2
record3
record4|val4
awk -F'|' 'NF>1 {print $1}' testing
record1
record2
record4
Alternatively, you could use
awk -F'|' '$1==$0'
If no separator is present, then field one will contain the whole line.

How to extract only numbers with awk

Hello i have the following output:
replication complete (rid=969811 lid=969811)
or sometimes:
no change of listener transaction id for last 0 checks (rid=971489 lid=970863)
now i want to use awk to get only the numbers from rid and lid, the following works only with the first option
|awk -F'[^0-9]*' '{print $2-$3}'
$ echo "no change of listener transaction id for last 0 checks (nid=971491 lid=970876)" |
awk -F'[()]' '{gsub(/[^0-9 ]/,"",$2); print $2}'
971491 970876
$ echo "no change of listener transaction id for last 0 checks (nid=971491 lid=970876)" |
awk -F'[()= ]' '{print $(NF-3), $(NF-1)}'
971491 970876
$ echo "no change of listener transaction id for last 0 checks (nid=971491 lid=970876)" |
awk -F'[()= ]' '{for (i=1;i<=NF;i++) m[$i]=$(i+1); print m["nid"], m["lid"]}'
971491 970876
$ echo "no change of listener transaction id for last 0 checks (nid=971491 lid=970876)" |
awk '{gsub(/.*\(|[^0-9 ]+|\).*$/,"")}1'
971491 970876
etc., etc.... The right one for you really depends what else you plan to do with the text.
Hmm, I now see in your question that you MIGHT want to print the subtraction of one number from the other instead of printing the numbers as I thought. Here's one way based on the above:
$ echo "no change of listener transaction id for last 0 checks (nid=971491 lid70876)" |
awk -F'[()= ]' '{print $(NF-3) - $(NF-1)}'
615
Alternatives left as an exercise!
You can use this awk, if your goal is to work with rid and lid values.
awk -F\(rid=\|lid=\) '{print $2-$3}' yourfile
(OR)
awk 'BEGIN{FS="(rid=|lid=)"} {print $2-$3}' yourfile
awk -F'=' '{print int($2)-int($3)}'
Works because of the way awk parses strings.
Another solution, this works in GNU-awk 4 only .... Defining Fields by Content in GAWK
echo "no change of listener transaction id for last 0 checks (rid=971489 lid=970863)" |
gawk -vFPAT='[0-9]+' '{print $(NF-1), $NF}'
you get,
971489 970863
echo "replication complete (rid=969811 lid=969811)" |
gawk -vFPAT='[0-9]+' '{print $(NF-1), $NF}'
you get,
969811 969811
Note: if, you want to do subtraction
echo "replication complete (rid=969811 lid=969811)" |
gawk -vFPAT='[0-9]+' '{print $(NF-1)-$NF}'
you get,
0