I have a script chk.awk to which I want to pass some command line arguments. It has awk statements, sed command etc. Just for example I have taken a small program below to which I want to pass command line arguments.
#!/bin/bash
var1=$1
gawk '
BEGIN {
printf "argc = %d\n argv0=%s\n argv1=%s\n var1=%s\n",ARGC,ARGV[0],ARGV[1],$var1
}'
But when I try :
$ sh chk.awk 10 20
argc = 1
argv0=gawk
argv1=
var1=
Above I tried to display the command line arguments by both ways i.e. argv & $1, but none of them work. Can anyone let me know where I am going wrong here? What is the correct way to do that?
The problem is that you give arguments to the shell script, but not to the awk script.
You must add "$#" to the call of gawk.
#!/bin/bash
var1=$1
gawk '
BEGIN {
printf "argc = %d\n argv0=%s\n argv1=%s\n var1=%s\n",ARGC,ARGV[0],ARGV[1],$var1
}' "$#"
Otherwise you will your arguments in the shell-script and they will be not passed to gawk.
Update 1
If you have additional args (e.g. filenames that are to be processed),
you must remove the first portition of args first (in the BEGIN section):
#!/bin/bash
var1=$1
gawk '
BEGIN {
printf "argc = %d\n argv0=%s\n argv1=%s\n var1=%s\n",ARGC,ARGV[0],ARGV[1],$var1;
delete ARGV[1]
}' "$#" filename
Related
I have the following issue. I want to run a script with 2 parameters like:
./Myscript.sh $1 $2
$1 is a number, nothing special but $2 It's actually a message that looks like this:
“My message`-12355, this is a message !56432-I am sure it`s a message-46583”.
This message was actually extracted with an awk from some log files. Myscript.sh executes a curl http post and uses the $1 and $2 as parameters for creating the json in curl command like
-d '{"number":"$1","message":"$2"}'
My question is how do I “escape” the argument $2 since the message contains special characters?
Thanks
I'm calling Myscript.sh from another script in a awk command using:
system(./Myscript.sh “$1” \”$2\”)
I was thinking to use backslashes to “escape” but this not seems to work. Any ideas or help would be great. Thanks a lot!
I suggest to use " and not “.
system("./Myscript.sh \"" $1 "\" \"" $2 "\"")
you have exclamation mark ("!") in your shell $2 - I'd safely single-quote them if I were you ::
sh: ./Myscript.sh: No such file or directory
system() command :::
'./Myscript.sh' '1114111'
'My message`-12355, this is a
message !56432-I'\''m sure it`s a message-46583'
# gawk profile, created Mon Jan 9 05:37:09 2023
# Rule(s)
1 ' {
1 print "system() command :::\f\f\r\t",
system_cmd = escSQ($1) (_ = " ")
escSQ($2)_ escSQ($3)
1 system(system_cmd)
}
3 function escSQ(__,_) {
3 _ = "\47"
3 gsub(_,"&\\" (_)_,__)
3 return (_)(__)_
}'
ps : this approach is okay only if none of the command items have items that need to be interpreted by the shell, e.g. ~ (as prefix for script itself) or $? etc
When running perl -n or perl -p, each command line argument is taken as a file to be opened and processed line by line. If you want to pass command line switches to that script, how can I do that?
There are three primary ways of passing information to Perl without using STDIN or external storage.
Arguments
When using -n or -p, extract the arguments in the BEGIN block.
perl -ne'BEGIN { ($x,$y)=splice(#ARGV,0,2) } f($x,$y)' -- "$x" "$y" ...
Command-line options
In a full program, you'd use Getopt::Long, but perl -s will do fine here.
perl -sne'f($x,$y)' -- -x="$x" -y="$y" -- ...
Environment variables
X="$x" Y="$y" perl -ne'f($ENV{X},$ENV{Y})' -- ...
Here is a short example program (name it t.pl), how you can do it:
#!/bin/perl
use Getopt::Std;
BEGIN {
my %opts;
getopts('p', \%opts);
$prefix = defined($opts{'p'}) ? 'prefix -> ' : '';
}
print $prefix, $_;
Call it like that:
perl -n t.pl file1 file2 file3
or (will add a prefix to every line):
perl -n t.pl -p file1 file2 file3
I've written my first script, one in which I want to know if 2 files have the same values in a specific column.
Both files are WEKA machine-learning prediction outputs for different algorithms, hence they have to be in the same format, but the prediction column would be different.
Here's the code I've written based on the tutorial presented in https://linuxconfig.org/bash-scripting-tutorial-for-beginners:
#!/bin/bash
lineasdel1=$(wc -l $1 | awk '{print $1}')
lineasdel2=$(wc -l $2 | awk '{print $1}')
if [ "$lineasdel1" != "$lineasdel2" ]; then
echo "Files $1 and $2 have different number of lines, unable to perform"
exit 1
fi
function quitalineasraras {
awk '$1!="==="&&NF>0'
}
function acomodo {
awk '{gsub(/^ +| +$/, ""); gsub(/ +0/, " W 0"); gsub(/ +1$/, " W 1"); gsub(/ +/, "\t") gsub(/\+\tW/, "+"); print}'
}
function procesodel1 {
quitalineasraras "$1" | acomodo
}
function procesodel2 {
quitalineasraras "$2" | acomodo
}
el1procesado=$(procesodel1)
el2procesado=$(procesodel2)
function pegar {
paste <(echo "$el1procesado") <(echo "$el2procesado")
}
function contarintersec {
awk 'BEGIN {FS="\t"} $3==$8 {n++} END {print n}'
}
unido=$(pegar)
interseccion=$(contarintersec $unido)
echo "Estos 2 archivos tienen $interseccion coincidencias."
I ran all individual codes of all functions in the terminal and verified they work successfully (I'm using Linux Mint 19.2). Script's permissions also have been changed to make it executable. Paste command also is supposed to work with that variable syntax.
But when I run it via:
./script.sh file1 file2
if both files have the same number of lines, and I press enter, no output is obtained; instead, the terminal opens an empty line with cursor waiting for something. In order to write another command, I've got to press CTRL+C.
If both files have different number of lines the error message prints successfully, so I think the problem has something to do with the functions, with the fact that awk has different syntax for some chores, or with turning the output of functions into variables.
I know that I'm missing something, but can't come up with what could be.
Any help will be appreciated.
what could be.
function quitalineasraras {
awk '$1!="==="&&NF>0'
}
function procesodel1 {
quitalineasraras "$1" | acomodo
}
el1procesado=$(procesodel1)
The positional variables $1 are set for each function separately. The "$1" inside procesodel1 expands to empty. The quitalineasraras is passed one empty argument "".
The awk inside quitalineasraras is passed only the script without the filename, so it reads the input for standard input, ie. it waits for the input on standard input.
The awk inside quitalineasraras without any file arguments makes your script seem to wait.
Trying to write a bash script containing nested dollar variables and I can't get it to work :
#!/bin/bash
sed '4s/.*/$(grep "remote.*$1" /home/txtfile)/' /home/target
The error says :
sed / -e expression #1, char 30: unkown option to 's'
The problem seems to come from $1 which need to be replaced by the parameter passed from the bash call and then the whole $(...) needs to be replaced by the command call so we replace the target line 4 by the string output.
Variable expansion and Command substitution won't be done when put inside single quotes, use double quotes instead:
sed "4s/.*/$(grep "remote.*$1" /home/txtfile)/" /home/target
Your approach is wrong, the right way to do what you want is just one command, something like this (depending on your possible $1 values and input file contents which you haven't shown us):
awk -v tgt='remote.*$1' '
NR==FNR { if ($0 ~ tgt) str = str $0 ORS; next }
FNR==4 { printf "%s", str; next }
{ print }
' /home/txtfile /home/target
Can you please help me solve this puzzle? I am trying to print the location of a string (i.e., line #) in a file, first to the std output, and then capture that value in a variable to be used later. The string is “my string”, the file name is “myFile” which is defined as follows:
this is first line
this is second line
this is my string on the third line
this is fourth line
the end
Now, when I use this command directly at the command prompt:
% awk ‘s=index($0, “my string”) { print “line=” NR, “position= ” s}’ myFile
I get exactly the result I want:
% line= 3, position= 9
My question is: if I define a variable VAR=”my string”, why can’t I get the same result when I do this:
% awk ‘s=index($0, $VAR) { print “line=” NR, “position= ” s}’ myFile
It just won’t work!! I even tried putting the $VAR in quotation marks, to no avail? I tried using VAR (without the $ sign), no luck. I tried everything I could possibly think of ... Am I missing something?
awk variables are not the same as shell variables. You need to define them with the -v flag
For example:
$ awk -v var="..." '$0~var{print NR}' file
will print the line number(s) of pattern matches. Or for your case with the index
$ awk -v var="$Var" 'p=index($0,var){print NR,p}' file
using all uppercase may not be good convention since you may accidentally overwrite other variables.
to capture the output into a shell variable
$ info=$(awk ...)
for multi line output assignment to shell array, you can do
$ values=( $(awk ...) ); echo ${values[0]}
however, if the output contains more than one field, it will be assigned it's own array index. You can change it with setting the IFS variable, such as
$ IFS=$(echo -en "\n\b"); values=( $(awk ...) )
which will capture the complete lines as the array values.