awk — getting minus instead of FILENAME - unix

I am trying to add the filename to the end of each line as a new field. It works except instead of getting the filename I get -.
Base file:
070323111|Hudson
What I want:
070323111|Hudson|20150106.csv
What I get:
070323111|Hudson|-
This is my code:
mv $1 $1.bak
cat $1.bak | awk '{print $0 "|" FILENAME}' > $1

- is the way to present the filename when there is not such info. Since your are doing cat $1.bak | awk ..., awk is not reading from a file but from stdin.
Instead, just do:
awk '...' file
in your case:
awk '{print $0 "|" FILENAME}' $1.bak > $1
From man awk:
FILENAME
The name of the current input file. If no files are specified on the
command line, the value of FILENAME is “-”. However, FILENAME is
undefined inside the BEGIN rule (unless set by getline).

Related

Pass Variable in awk and match it with $1

My requirement is to split a file based on the first field.
My file looks something like this :
aaa|12345
bbb|45679
aaa|334564
ccc|qewqw
Now my awk command works just fine and splits the file with respect to the first field value.
awk -F\| '{f=($1); print $2 > f}' /myfile
Result : File name aaa has the below rows :
12345
334564
Now , I want to make it input driven , that is from a script i will enter the value aaa to this awk command and it will match with $1 and create the file like above. I tried with awk -v to take the value as input, but its not working the way I want it to.
Any help would be much appreciated.
Thanks in advance.
Like this?:
$ awk -v f=aaa -F\| 'f==$1{print $2 > f}' file
$ ls
aaa file
$ cat aaa
12345
334564
Explained:
$ awk -v f=aaa -F\| ' # set input field separator and var f="aaa"
f==$1 { # if f ie. "aaa" equals to first field value
print $2 > f # write second field value to file f ie. "aaa"
}' file
awk -v var=$input_value -F\| '{print $2 > var}' myfile
In your code in comments the problem is with f=($var). I think you wanted f=var.
cat file | awk -v inp=aaa -F\| '$1 ~ inp { print $2 > inp }'

Specifying the order of output using awk

I have the following file called testfile, with the following contents:
{"items":[{"ogit\/_created on":1413388512511,"\/environmentType":"PROD","\/soxRelevant":"true","\/environmentName":"dbVertical"}]}
I used the following awk command to get the values for soxRelevant, environment type and environment name.
cat test file | tr -d '"' | awk 'BEGIN {RS=","; FS=":"; ORS=",";} /soxRelevant/ {print $2}; /environmentType/ {print $2}; /environmentName/ {print $2};'
The output was as follows
PROD,true,dbVertical,
However I want the soxRelevant output first followed by environment type then environment name, as specified in the awk command:
I want the output to be:
true, PROD, dbVertical
How do I do this?
You could push the elements to an array then print them in the END block:
awk 'BEGIN {RS=ORS=","; FS=":"}
/soxRelevant/ {a[1]=$2}
/environmentType/ {a[2]=$2}
/environmentName/ {a[3]=$2}
END{for(n=1;n<=3;++n)print a[n]}'

unix command, remove white spaces in text file with delimeter

I have text file,
Input file:
sno|name|lab|result|dep
1|aaa|ALB|<= 3.67|CHE
2|bbb|WBC|> 7.2|FVC
3|ccc|RBC|> 14|CHE
Output file:
sno|name|lab|result|dep
1|aaa|ALB|<=3.67|CHE
2|bbb|WBC|>7.2|FVC
3|ccc|RBC|>14|CHE
How to remove white spaces in column 4(result)?
If you can remove spaces from everything, just use sed:
sed 's/ //g' input.txt > output.txt
Or even tr (translate):
tr -d ' ' < input.txt > output.txt
Otherwise, if you need to edit just the fourth column, use awk. The following command considers | as field separator (-F \|) and then outputs files using | as output field separator (-vOFS=\|).
awk -F \| -vOFS=\| '{gsub(/ /, "", $4); print; }' input.txt > output.txt

awk syntax to invoke function with argument read from a file

I have a function
xyz()
{
x=$1*2
echo x
}
then I want to use it to replace a particular column in a csv file by awk.
File input.csv:
abc,2,something
def,3,something1
I want output like:
abc,4,somthing
def,6,something1
Command used:
cat input.csv|awk -F, -v v="'"`xyz "$2""'" 'BEGIN {FS=","; OFS=","} {$2=v1; print $0}'
Open file input.csv, calling function xyz by passing file 2nd filed as argument and result is stored back to position 2 of file, but is not working!
If I put constant in place of $2 while calling function it works:
Please help me to do this.
cat input.csv|awk -F, -v v="'"`xyz "14""'" 'BEGIN {FS=","; OFS=","} {$2=v1; print $0}'
This above line of code is working properly by calling the xyz function and putting the result back to 2nd column of file input.csv, but with only 14*2, as 14 is taken as constant.
There's a back-quote missing from your command line, and a UUOC (Useless Use of Cat), and a mismatch between variable v on the command line and v1 in the awk program:
cat input.csv|awk -F, -v v="'"`xyz "$2""'" 'BEGIN {FS=","; OFS=","} {$2=v1; print $0}'
^ Here ^ Here ^ Here
That should be written using $(…) instead:
awk -F, -v v="'$(xyz "$2")'" 'BEGIN {FS=","; OFS=","} {$2=v; print $0}' input.csv
This leaves you with a problem, though; the function xyz is invoked once by the shell before you start your awk script running, and is never invoked by awk. You simply can't do it that way. However, you can define your function in awk (and on the fly):
awk -F, 'BEGIN { FS = ","; OFS = "," }
function xyz(a) { return a * 2 }
{ $2 = xyz($2); print $0 }' \
input.csv
For your two-line input file, it produces your desired output.

AWK to print field $2 first, then field $1

Here is the input(sample):
name1#gmail.com|com.emailclient.account
name2#msn.com|com.socialsite.auth.account
I'm trying to achieve this:
Emailclient name1#gmail.com
Socialsite name2#msn.com
If I use AWK like this:
cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}'
it messes up the output by overlaying field 1 on the top of field 2.
Any tips/suggestions? Thank you.
A couple of general tips (besides the DOS line ending issue):
cat is for concatenating files, it's not the only tool that can read files! If a command doesn't read files then use redirection like command < file.
You can set the field separator with the -F option so instead of:
cat foo | awk 'BEGIN{FS="|"} {print $2 " " $1}'
Try:
awk -F'|' '{print $2" "$1}' foo
This will output:
com.emailclient.account name1#gmail.com
com.socialsite.auth.accoun name2#msn.com
To get the desired output you could do a variety of things. I'd probably split() the second field:
awk -F'|' '{split($2,a,".");print a[2]" "$1}' file
emailclient name1#gmail.com
socialsite name2#msn.com
Finally to get the first character converted to uppercase is a bit of a pain in awk as you don't have a nice built in ucfirst() function:
awk -F'|' '{split($2,a,".");print toupper(substr(a[2],1,1)) substr(a[2],2),$1}' file
Emailclient name1#gmail.com
Socialsite name2#msn.com
If you want something more concise (although you give up a sub-process) you could do:
awk -F'|' '{split($2,a,".");print a[2]" "$1}' file | sed 's/^./\U&/'
Emailclient name1#gmail.com
Socialsite name2#msn.com
Use a dot or a pipe as the field separator:
awk -v FS='[.|]' '{
printf "%s%s %s.%s\n", toupper(substr($4,1,1)), substr($4,2), $1, $2
}' << END
name1#gmail.com|com.emailclient.account
name2#msn.com|com.socialsite.auth.account
END
gives:
Emailclient name1#gmail.com
Socialsite name2#msn.com
Maybe your file contains CRLF terminator. Every lines followed by \r\n.
awk recognizes the $2 actually $2\r. The \r means goto the start of the line.
{print $2\r$1} will print $2 first, then return to the head, then print $1. So the field 2 is overlaid by the field 1.
The awk is ok. I'm guessing the file is from a windows system and has a CR (^m ascii 0x0d) on the end of the line.
This will cause the cursor to go to the start of the line after $2.
Use dos2unix or vi with :se ff=unix to get rid of the CRs.

Resources