Awk doesn`t work when it run at other path - linux

./oppa/loadParesr/spliter.sh [filename]
spliter.sh
#!/bin/sh
sort -k 1V,1 -k 2n,2 $1 -o $1
awk `{close(f);f=$1}{print > f".bed"}`
i try to run this shell at other path. sort command work well but
awk is doesn't work and i don't know why.

Close the file you're writing to, not just part of it's name, and always quote your shell variables, for example:
awk '{close(f); f=$1".bed"; print > f}' "$1"

Related

How to pass shell variable to awk command inside shell script

I just want to pass a shell variable that stores name of a file to awk command. When I searched this problem on the net I see many different options but none of them worked for me. I tried the followings:
#!/bin/bash
for i in "$#"
do
case $i in
-p=*|--producedfile=*)
PFILE="${i#*=}"
shift # past argument=value
*)
# unknown option
;;
esac
done
echo "PRODUCEDFILE = ${PFILE}"
awk -v FILE=${PFILE} '{print FILE $0}' #DIDNT WORK
awk '{print FILE $0}' ${PFILE} # DIDNT WORK
awk -v FILE=${PFILE} '{print $0}' FILE #DIDNT WORK
To pass a shell variable to awk, you correctly used -v option.
However, the shift was unnecessary (you're iterating options with for), ;; was missing (you have to terminate each case branch), as well as was the name of the file for awk to process. Fixed, your script looks like:
#!/bin/bash
for i in "$#"; do
case $i in
-p=*|--producedfile=*)
PFILE="${i#*=}"
;;
*)
# unknown option
;;
esac
done
echo "PRODUCEDFILE = ${PFILE}"
awk -v FILE="${PFILE}" '{print FILE, $0}' "${PFILE}"
Note however, awk already makes the name of the currently processed file available in the FILENAME variable. So, you could also write the last line as:
awk '{print FILENAME, $0}' "${PFILE}"

.sh script doesn't return variable correctly

I have created a file called alias.sh in which I have put this code:
#!/bin/bash
OUTPUT="$(alias | awk -F'[ =]' '{print $2}')"
echo "${OUTPUT}"
Whenever I run the command alias | awk -F'[ =]' '{print $2}' in a terminal, it correctly returns a list of set aliases in my preferred format.
However, when I execute the script like $ ./alias.sh, it simply returns an empty line.
The script works if I replace the alias | awk -F'[ =]' '{print $2}' command with the ls command. It even preserves line breaks.
Can anybody help me understand why the script does not return the expected result?
The actual reason for the error is because alias is not expanded when the shell is not interactive,
From the man bash page,
[..] Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt [..]
add the line below to the top of the script for force the expansion manually.
shopt -s expand_aliases
and then source the script and not execute it,
#!/bin/bash
shopt -s expand_aliases
output=$(alias | awk -F'[ =]' '{print $2}')
echo "$output"
and now source the script as
. ./myScript.sh
You use $2 in the AWK script. However, that is replaced by the shell as the second argument to the shell script, which is nothing. You need to escape the dollar-sign, as in \$2. Or not use double-quotes " around the sub-shell.

Difference between awk -FS and awk -f in shell scripting

I am new to shell scripting and I'm very confused between awk -FS and awk -f commands used. I've tried reading multiple pages on the difference between these two but was not able to understand clearly. Kindly help.
Here is an example:
Lets consider that a text file say, data.txt has the below details.
S.No Product Qty Price
1-Pen-2-10
2-Pencil-1-5
3-Eraser-1-2
Now, when i try to use the following command:
$ awk -f'-' '{print $1,$2} data.txt
I get the below output:
1 Pen
2 Pencil
3 Eraser
But when i use the command:
$ awk -FS'-' '{print $1,$2} data.txt
the output is:
1-Pen-2-10
2-Pencil-1-5
3-Eraser-1-2
I don't understand the difference it does using the -FS command. Could somebody help me out on what exactly happens between these two commands. Thanks!
You are more confused than you think. There is no -FS.
FS is a variable that contains the field separator.
-F is an option that sets FS to it's argument.
-f is an option whose argument is the name of a file that contains the script to execute.
The scripts you posted would have produced syntax errors, not the output you say they produced, so idk what to tell you...
-FS is not an argument to awk. -F is, as is -f.
The -F argument tells awk what value to use for FS (the field separator).
The -f argument tells awk to use its argument as the script file to run.
This command (I fixed your quoting):
awk -f'-' '{print $1,$2}' data.txt
tells awk to use standard input (that's what - means) for its argument. This should hang when run in a terminal. And should be an error after that as awk then tries to use '{print $1,$2}' as a filename to read from.
This command:
awk -FS'-' '{print $1,$2}' data.txt
tells awk to use S- as the value of FS. Which you can see by running this command:
awk -FS'-' 'BEGIN {print "["FS"]"}'

Pass parameter to an awk script file

If I want to pass a parameter to an awk script file, how can I do that ?
#!/usr/bin/awk -f
{print $1}
Here I want to print the first argument passed to the script from the shell, like:
bash-prompt> echo "test" | ./myawkscript.awk hello
bash-prompt> hello
In awk $1 references the first field in a record not the first argument like it does in bash. You need to use ARGV for this, check out here for the offical word.
Script:
#!/bin/awk -f
BEGIN{
print "AWK Script"
print ARGV[1]
}
Demo:
$ ./script.awk "Passed in using ARGV"
AWK Script
Passed in using ARGV
You can use -v as a command-line option to provide a variable to the script:
Say we have a file script.awk like this:
BEGIN {print "I got the var:", my_var}
Then we run it like this:
$ awk -v my_var="hello this is me" -f script.awk
I got the var: hello this is me
your hash bang defines the script is not shell script, it is an awk script. you cannot do it in bash way within your script.
also, what you did : echo blah|awk ... is not passing paramenter, it pipes the output of echo command to another command.
you could try these way below:
echo "hello"|./foo.awk file -
or
var="hello"
awk -v a="$var" -f foo.awk file
with this, you have var a in your foo.awk, you could use it.
if you want to do something like shell script accept $1 $2 vars, you can write a small shellscript to wrap your awk stuff.
EDIT
No I didn't misunderstand you.
let's take the example:
let's say, your x.awk has:
{print $1}
if you do :
echo "foo" | x.awk file
it is same as:
echo "foo"| awk '{print $1}' file
here the input for awk is only file, your echo foo doesn't make sense. if you do:
echo "foo"|awk '{print $1}' file -
or
echo "foo"|awk '{print $1}' - file
awk takes two input (arguments for awk) one is stdin one is the file, in your awk script you could:
echo "foo"|awk 'NR==FNR{print $1;next}{print $1}' - file
this will print first foo from your echo, then the column1 from file of course this example does nothing actual work, just print them all.
you can of course have more than two inputs, and don't check the NR and FNR, you could use the
ARGC The number of elements in the ARGV array.
ARGV An array of command line arguments, excluding options and the program argument, numbered from zero to ARGC-1
for example :
echo "foo"|./x.awk file1 - file2
then your "foo" is the 2nd arg, you can get it in your x.awk by ARGV[2]
echo "foo" |x.awk file1 file2 file2 -
now it is ARGV[4] case.
I mean, your echo "foo"|.. would be stdin for awk, it could by 1st or nth "argument"/input for awk. depends on where you put the -(stdin). You have to handle it in your awk script.

How to get extension of a file in shell script

I am trying to get file extension for a file in shell script. But without any luck.
The command I am using is
file_ext=${filename##*.}
and
file_ext = $filename |awk -F . '{if (NF>1) {print $NF}}'
But both of the commands failed to put value in variable file_ext. But when i try
echo $filename |awk -F . '{if (NF>1) {print $NF}}'
It gives me the desired result. I am new to shell script. Please describe the situation what is happening. And also how should I do it?
Thanks.
to get file extension, just use the shell
$ filename="myfile.ext"
$ echo ${filename##*.}
ext
$ file_ext=${filename##*.} #put to variable
$ echo ${file_ext}
ext
Spaces hurt.
Anyway you should do:
file_ext=$(echo $filename | awk -F . '{if (NF>1) {print $NF}}')
[Edit] Better suggestion by Martin:
file_ext=$(printf '%s' "$filename" | awk -F . '{if (NF>1) {print $NF}}')
That will store in $file_ext the output of the command.
You have to be careful when declaring variables.
variable1="string" # assign a string value
variable3=`command` # assign output from command
variable2=$(command) # assign output from command
Notice that you cannot put a space after the variable, because then it gets interpreted as a normal command.

Resources