.sh script doesn't return variable correctly - linux

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.

Related

Awk doesn`t work when it run at other path

./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"

Generating a bash script from a bash script

I need to generate a script from within a script but am having problems because some of the commands going into the new script are being interpreted rather than written to the new file. For example i want to create a file called start.sh in it I want to set a variable to the current IP address:
echo "localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')" > /start.sh
what gets written to the file is:
localip=192.168.1.78
But what i wanted was the following text in the new file:
localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')"
so that the IP is determined when the generated script is run.
What am i doing wrong ?
You're making this unnecessary hard. Use a heredoc with a quoted sigil to pass literal contents through without any kind of expansion:
cat >/start.sh <<'EOF'
localip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/')
EOF
Using <<'EOF' or <<\EOF, as opposed to just <<EOF, is essential; the latter will perform expansion just as your original code does.
If anything you're writing to start.sh needs to be based on current variables, by the way, be sure to use printf %q to safely escape their contents. For instance, to set your current $1, $2, etc. to be active during start.sh execution:
# open start.sh for output on FD 3
exec 3>/start.sh
# build a shell-escaped version of your argument list
printf -v argv_str '%q ' "$#"
# add to the file we previously opened a command to set the current arguments to that list
printf 'set -- %s\n' "$argv_str" >&3
# pass another variable through safely, just to be sure we demonstrate how:
printf 'foo=%q\n' "$foo" >&3
# ...go ahead and add your other contents...
cat >&3 <<'EOF'
# ...put constant parts of start.sh here, which can use $1, $2, etc.
EOF
# close the file
exec 3>&-
This is far more efficient than using >>/start.sh on every line that needs to append: Using exec 3>file and then >&3 only opens the file once, rather than opening it once per command that generates output.

Single Quote issue with gawk and shell script

I am writing a small script to map all the current memory being used by services running in a server. However, I am facing a problem doing that. My script is quite simple. I'm using pmap to find out memory being used and trying add up all the pid of a service running.
#!/bin/bash
result=`$pgrep java`
wc=`$pmap -x $result | wc -l`
gawk=`$pmap -x $result | gawk 'NR==$wc{print $3}'`
echo "$gawk"
Now, my problem is that gawk uses single quote when searching for a specific pattern (gawk 'NR==$wc{print $3}') but shell script gives me error because then meaning of single quote is different in shell from gawk.
Based on your comment, it looks like you're trying to do this:
pmap -x "$(pgrep java)" | awk '{s=$3}END{print s}'
This prints the third column of the last line of the output of pmap -x, with the PID of the running java process. In some versions of awk, you can simply do 'END{print $3}' but this isn't guaranteed to work.
pmap -x $result | gawk 'NR==$wc{print $3}' is not doing what you think it is. (I have replaced your $pmap with pmap, but my analysis is only of the gawk command so if that is incorrect it should be irrelevant.) The shell is going to pass the literal string NR==$wc{print $3} to awk, but it appears that you want awk to see the value of the shell variable $wc rather than the literal string $wc. When awk sees $wc, it treats wc an an uninitialized value, so $wc become equivalent to $0, and awk will print any line whose content matches the line number. The standard way to pass the shell variable into awk is:
pmap -x $result | gawk 'NR==w{print $3}' w=$wc
This assignes the shell variable wc to the awk variable w, and will print the third column of that line.
Note that there are a number of issues with this shell script, but this seems to be the core confusion.

How to pass AWK output into variable?

I have a small bash script that greps/awk paragraph by using a keyword.
But after adding in the extra codes : set var = "(......)" it only prints a blank line and not the paragraph.
So I would like to ask if anyone knows how to properly pass the awk output into a variable for outputting?
My codes:
#!/bin/sh
set var = "(awk 'BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/FileHeader/' /root/Desktop
/logs/Default.log)"
echo $var;
Thanks!
Use command substitution to capture the output of a process.
#!/bin/sh
VAR="$(awk 'BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/FileHeader/' /root/Desktop/logs/Default.log)"
echo "$VAR"
some general advice with regards to shell scripting:
(almost) always quote every variable reference.
never put spaces around the equals sign in variable assignment.
You need to use "command substitution". Place the command inside either backticks, `COMMAND` or, in a pair of parentheses preceded by a dollar sign, $(COMMAND).
To set a variable you don't use set and you can't have spaces before and after the =.
Try this:
var=$(awk 'BEGIN{RS=ORS="\n\n";FS=OFS="\n"}/FileHeader/' /root/Desktop/logs/Default.log)
echo $var
You gave me the idea of this for killing a process :). Just chromium to whatever process you wanna kill.
Try this:
VAR=$(ps -ef | grep -i chromium | awk '{print $2}'); kill -9 $VAR 2>/dev/null; unset VAR;
anytime you see grep piped to awk, you can drop the grep. for the above,
awk '/^password/ {print $2}'
awk can easily replace any text command like cut, tail, wc, tr etc. and especally multiple greps piped next to each other. i.e
grep some_co.mand | a | grep b ... to | awk '/a|b|and so on/ {some action}.
Try to create a variable coming from vault/Hashicorp, when using packer template variables, like so:
BUILD_PASSWORD=$(vault read secret/buildAccount| grep ^password | awk '{print $2}')
echo $BUILD_PASSWORD
You can to the same with grep ^user

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