Getting first line argument in bash after forking processes - bash

Here is my file.sh bash script:
#!/bin/bash
$(awk '/[ \t]+'$1'\/'$2'/' /etc/servicies) | awk '{print '$1'}';
if I run:
file.sh 21 tcp
it should print ftp. But I get that error:
./file.sh: line 2: ftp: command not found
Can anybody explain me a little bit why that error and how to fix it?
Thanks.

awk '/[ \t]+'$1'\/'$2'/ { print $1 }' /etc/services

Why do you use the $( ... ) construct? It is replaced by the output of the enclosed commands by bash, so your pipeline becomes something like
ftp 21/tcp xxx_master # ftp / XXX
which triggers the mentioned error.
Solution: Just remove the $( and ) and everything should work as you expected.

awk '$2==A && $3=B, NF=1' FPAT='[^ /]+' A=$1 B=$2 /etc/services

kinda hard to understand but...
$(whatever) executes its output...
So, assuming that
$(awk '/[ \t]+'$1'\/'$2'/' /etc/services)
the part inside the $() gets you as output
ftp blahblahblah
it will first try to execute it and only after pass the execution output to the second awk piping.
Just remove the $() syntax, in that way the output of the first awk will be sent to the later steps.
Btw, please, instead of doing
cat xxxx | dosomething
try doing
dosomething xxxxx

Related

Is it possible to pass a script to awk inside a shell variable?

Is it possible to store an awk script inside a shell variable; for example:
export script="'{printf(\$2); printf("\"\\n\"");}'"
echo $script
'{printf($2); printf("\n");}'
The script functions properly when I call it directly as such:
awk '{printf($2); printf("\n");}' testFile.txt
prints proper output
When I try and pass the script as a shell variable, I run into issues.
awk $script testFile.txt
awk: syntax error at source line 1
context is
>>> ' <<<
missing }
awk: bailing out at source line 1
I get a slightly different error when I wrap the variable in double quotes
awk "$script" testFile.txt
awk: syntax error at source line 1
context is
>>> ' <<<
awk: bailing out at source line 1
I'm still learning exactly how shell expansions work, I would appreciate any suggestions about what I am missing here.
Error in your quoting
export script='{printf($2); printf("\n");}'
awk "${script}" YourFile
I am not sure about the proper answer to this, but a very ugly (and probably unstable depending on the $script contents) workaround would be:
echo $script | awk '{print "awk "$0" testFile.txt"}' | bash
This is just printing the contents of $script in an awk statement that is then executed by bash. I am not particularly proud of this, but maybe it helps!
When you type
awk '{printf($2); printf("\n");}' testFile.txt
awk only sees {printf($2); printf("\n");} -- the shell removes the quotes
(see Quote Removal in the bash manual)
Heed #NeronLeVelu's answer.

Issue while processing a line using awk in unix

I am running realpath command on each line of a file. Two sample lines of file are
$HOME:1:2
$HOME:1:2 3
I am expecting output of above two lines after running my command as:
/home/mjain8:1:2
/home/mjain8:1:2 3
The awk command I am running is awk 'BEGIN{cmd="realpath "}{cmd$0|getline;print $0;}' FS=':' OFS=':'
Now, when I run the command on first line it runs fine and gives me the desired output. But for line 2 of file (shown above) the output is /home/mjain8:1:2 (and NOT /home/mjain8:1:2 3). That is the output only contains line before space.
Can someone please point what am I doing wrong. Also, in case you have suggestion to use any other command please let me know same too. I have been struggling to do same using awk since last 2 days.
I want to make it portable so that it run on as many shells as possible.
With shell's while loop it will be much simpler, could you please try following. It worked fine for me.
while IFS=':' read -r path rest
do
real=$(realpath "$path")
echo "$real:$rest"
done < "Input_file"
Above code has real variable to first have realpath command's value and then it prints its output along with rest variable, in case you want to directly print them as per tripleee's comment use following then.
while IFS=':' read -r path rest
do
echo "$(realpath "$path"):$rest"
done < "Input_file"
With Perl-one liner also, you could do it easily
> export HOME=/home/mjain8
> cat home.txt
$HOME:1:2
$HOME:1:2 3
> perl -F: -lane ' {$F[0]=$ENV{HOME} ;print join(":",#F) } ' home.txt
/home/mjain8:1:2
/home/mjain8:1:2 3
> perl -F: -lane ' {$F[0]=$ENV{HOME} if $F[0]=~/\$HOME/;print join(":",#F) } ' home.txt # if you need to explicity check if it is HOME
/home/mjain8:1:2
/home/mjain8:1:2 3
>

Cannot grep a file from one line number to another in shell script

I am unable to grep a file from a shell script written. Below is the code
#!/bin/bash
startline6=`cat /root/storelinenumber/linestitch6.txt`
endline6="$(wc -l < /mnt/logs/arcfilechunk-aim-stitch6.log.2017-11-08)"
awk 'NR>=$startline6 && NR<=$endline6' /mnt/logs/arcfilechunk-aim-stitch6.log.2017-11-08 | grep -C 100 'Error in downloading indivisual chunk' > /root/storelinenumber/error2.txt
The awk command is working on standalone basis though when the start and end line numbers are given manually.
There was an issue with the syntax. The last line was modified to
awk 'NR>='"$startline9"' && NR<='"$endline9"'' /mnt/logs/arcfilechunk-aim-stitch9.log | grep -C 100 'Error in downloading indivisual chunk' >> /root/storelinenumber/error.txt
It solved the issue.
You have your attempted variable expansions within single quotes, meaning that they won't actually be expanded.
When passing shell variables into awk, I prefer them to be actual first-class awk variables so I don't have to worry about that sort of stuff:
awk -vstl=$startline6 -vendl=$endline6 'NR>=stl && NR<=endl ...

Bash grep command starts with or ends with

I'm after a command that will return results based on a pattern match that starts with or ends with a the given pattern.
This is what i have so far.
"cat input.txt | grep "^in|in$"
My main problem is that i cant get the (or) to work but i can get them to work individually.
Thanks for your help in advance.
try this:
grep "^in\|in$" input.txt
by default, grep use BRE, you have to escape the |. Or use grep's -E or -P, in order to avoid escaping those char with special meaning.
P.S, the cat is no necessary.
This awk should work:
awk '/^start|end$/' file
It will print all lines starting with start or ending with end
cat file
nothing
start with this
or it does have an end
or the end is near
awk '/^start|end$/' file
start with this
or it does have an end
Have you thought of using egrep rather than grep? Using the following should work for what you're after:
egrep "^in|in$" input.txt
There's no need to have the cat at the start, the above will work fine.

Bash/Awk: How can I run a command using bash or awk

How can I run a command in bash, read the output it returns and check if there's the text "xyz" in there in order to decide if I run another command or not?
Is it easy?
Thanks
if COMMAND | grep -q xyz; then
#do something
fi
EDIT: Made it quiet.
For example:
command1 | grep "xyz" >/dev/null 2>&1 && command2
run command1
its output filer with grep
discard output from the grep
and if the grep was successful (so found the string)
execute the command2
You can pipe the output of the command to grep or grep -e.
Your specification is very loose, but here is an idea to try
output="$(cmd args ....)"
case "${output}" in
*targetText* ) otherCommand args ... ;;
*target2Text* ) other2Command ... ;;
esac
I hope this helps.
While you can accomplish this task many different ways, this is a perfect use for awk.
prv cmd | awk '/xyx/ {print "cmd" } ' | bash
this is what you want
for example,
i have a text file called temp.txt that only contains 'xyz'
If i run the following command I will exepct the output "found it"
$ cat temp.txt | awk '/xyz/ {print "echo found it"}' | bash
> found it
so what I am doing is piping the output of my previous command into awk, who is looking for the pattern xyz (/xyz/). awk will print the command, in this case echo found it, and pipe it to bash to execute them. simple one-liner doing what you asked. note you can customize the regex that awk looks for.

Resources