error in awk of shell script - shell

I am getting the below error ith my code.What is missing in it? My goal is to print 13.0.5.8 in $version
#!/bin/ksh
file="abc_def_APP_13.0.5.8"
if echo "$file" | grep -E "abc_def_APP"; then
echo "Version found: $file"
version1=(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)
version2=(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)
echo $version1
echo $version2
version=$version$version2
echo $version
else
echo "Version not found"
fi
Please find below the error:
./version.sh: line 7: syntax error near unexpected token `|'
./version.sh: line 7: ` version1=(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)'
./version.sh: line 9: syntax error near unexpected token `|'
./version.sh: line 9: ` version2=(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)'
./version.sh: line 18: syntax error near unexpected token `else'

There's no need for awk at all. Just trim every character before the last underscore, like so:
file="abc_def_APP_13.0.5.8"
version="${file##*_}"
echo "$version"
See http://mywiki.wooledge.org/BashFAQ/073 for documentation on this technique, or see "parameter expansion" in bash's own docs.
To treat the last segment separately is also straightforward:
file="abc_def_APP_13.0.5.8"
version="${file##*_}" # result: 13.0.5.8
version_end="${version##*.}" # result: 8
version_start="${version%.*}" # result: 13.0.5
echo "${version_start}/${version_end}" # result: 13.0.5/8
Because this happens internally to bash, without executing any external commands (such as awk), it should be considerably faster to execute than other approaches given.

The problem is your backticks are missing $ you need to fix the following two lines like so:
version1=$(echo $file | awk -F_ '{print $NF}' | cut -d. -f1-3)
version2=$(echo $file | awk -F_ '{print $NF}' | cut -d. -f4-)
This will fix the syntactical errors. The following line doesn't make much sense as $version hasn't been initialize yet:
version=$version$version2
Did you mean:
version="${version1}.${version2}"
A side note you are using the -E option with grep but you aren't using any extended regexp features, in fact you are doing a fixed string string search so -F is more appropriate. You probably also want to use the -q option to suppress the output from grep.
Personally I would do:
file="abc_def_APP_13.0.5.8"
echo "$file" | awk '/abc_def_APP/{print "Version found: "$0;
print $4,$5,$6;
print $7;
print $4,$5,$6,$7;
next}
{print "Version not found"}' FS='[_.]' OFS=.
If you just want the version number in the variable version then why not simply:
version=$(echo "$file" | grep -o '[0-9].*')

It can all be done in a single awk command and without additional cut command. Consider following command:
read version1 version2 < <(echo $file|awk -F "[_.]" '{
printf("%s.%s.%s ", $4, $5, $6); printf("%s", $7);
for (i=8; i<=NF; i++) printf(".%s", $i); print ""}')
echo "$version1 :: $version2"
OUTPUT
13.0.5 :: 8

Related

unexpected EOF while looking for matching error

I am running below script and getting
error script.sh: line 9: unexpected EOF while looking for matching `''
script.sh: line 15: syntax error: unexpected end of file.
Though I tried to run line 9 manually n it runs without error.
alias gxt="awk -F "_" '{print \$1}' test | uniq"
count = $(cat test | awk -F "_" '{print $1} | uniq | wc -l)
for i in {1..count};
do
User=$(gxt | head -n $i)
recharge=$(grep -E "$User.recharge" test| awk -F "_" '{print $3}' | xargs )
total1=( $((${recharge// /+})))
sales=$(grep -E "$User.sale" test| awk -F "_" '{print $3}' | xargs )
total2=( $((${sales// /+})))
balance=`expr $total1 - $total2`
echo $User.balance.$balance >> result
done
Other than the issues already reported and those exposed by shellcheck, there is another issue:
for i in {1..count};
'count' cannot be a variable. It can only be a constant.
Change it to
for ((i = 1; i <= count; i++)); do whatever ; done
count=$(cat test | awk -F "_" '{print $1}` | uniq | wc -l)
missing ' at the end of {print $1}
Inadvertently added spaces around =

what does this bash script line of code mean

I am new to shell scripting and I found following line of code in a given script.
Could someone explain me with an example what the following line of code means
Path=`echo $line | awk -F '|' '{print $1}'`
echo $line will print the value of the variable $line, the | symbol means that the output of this will be passed (or piped) to another program/command/script. I will not attempt to explain awk here, but what is done above is that the output from the echo $line is taken and processed with it.
the option -FS as per awk man page means
-F fs Use fs for the input field separator
so the string after it will be used to split the input string given to awk into different fields. Example, you variable $line has a value of a|b it will be split into two fields a and b. What is to be done with this is specified within the '{}' expression.
Again, what can be done in there is next to infinite, here the only thing that is done is to print the first field which can be accessed with $1, or a in the above example ($2 would be b as can be guessed).
Finally, the output of this whole operation is then stored in the variable Path.
to summarize:
line="a|b"
echo $line | awk -F '|' '{print $1}'
> a
Path=`echo $line | awk -F '|' '{print $1}'`
echo $Path
> a
echo $line | awk -F '|' '{print $1}'
Explanation:
echo -> display a line of text
$line -> parameter expansion read the line
| -> A pipeline is a sequence of one or more commands separated by one of the control operators |
awk -> Invoke awk program
-F '|' -> Field separator as | for the data feed
'{print $1}' -> Print the first field
Example
echo 'a|b|c' | awk -F '|' '{print $1}'
will print a
I think this is just a complicated way to express
echo ${line%%|*}
i.e. write to stdout the part of the content of the variable line which goes up to - but not including - the first vertical bar.
Path=`echo $line | awk -F '|' '{print $1}'`
^ ^ ^ ^
| | | |
| | | print 1st column
| | |
| | input field separator
| |
| echo variable line
|
variable Path
-F'|' - by default awk splits record/line/row into columns by single space, but with |, awk splits by pipe
Above one can be written as
Path=$( awk -F '|' '{ print $1 }' <<< "$line" )
Suppose say
$ line="1|2|3"
$ Path=$( awk -F '|' '{ print $1 }' <<< "$line" )
$ echo $Path; # you get first column
1
Same as
$ Path=$( cut -d'|' -f1 <<< "$line" )
$ echo $Path;
1
the default field separator is ' ', if you have -F , means change default separator to '|'

Echo without a newline character results a syntax error

I am writing a shell script and I would like to have this code
echo $(awk '{print $1}' /proc/uptime) / 3600 | bc
without the newline character at the end.
I wanted to write it using echo -n, but this code
echo -n $(awk '{print $1}' /proc/uptime) / 3600 | bc
results a syntax error:
(standard_in) 1: syntax error
Can you help me with this?
Thank you very much!
echo $(awk '{print $1}' /proc/uptime) / 3600 | bc | tr -d "\n"
Alternatives:
echo -n $(($(cut -d . -f 1 /proc/uptime)/3600))
mapfile A </proc/uptime; echo -n $((${A%%.*}/3600))
A solution using echo -n:
echo -n $(echo $(awk '{print $1}' /proc/uptime) / 3600 | bc)
In general, if foo produces a line of output, you can print the same output without a newline using echo -n $(foo), even if foo is complicated.
A more straightforward solution using pure awk (since awk does arithmetic and output formatting, there's not much point in using both awk and bc):
awk '{printf("%d", $1 / 3600)}' /proc/uptime

Bash for loop error

I have a script in bash what take from LocLog a ip from collumn 8 :
#!/bin/bash
for i in $(cat /scripts/logs/LocLog | awk '{print $8}' | sort | uniq);
do
php /scripts/a.php $i;
done
The script give an error:
bash -x log
'og: line 2: syntax error near unexpected token `
'og: line 2: `for i in $(cat /scripts/logs/LocLog | awk '{print $8}' | sort | uniq);
Any ideeas?
Get rid of the semicolon at the end of the for line.

Bash awk one-liner not printing

Expecting this to print out abc - but I get nothing, every time, nothing.
echo abc=xyz | g="$(awk -F "=" '{print $1}')" | echo $g
A pipeline isn't a set of separate assignments. However, you could rewrite your current code as follows:
result=$(
echo 'abc=xyz' | awk -F '=' '{print $1}'
)
echo "$result"
However, a more Bash-centric solution without intermediate assignments could take advantage of a here-string. For example:
awk -F '=' '{print $1}' <<< 'abc=xyz'
Other solutions are possible, too, but this should be enough to get you started in the right direction.

Resources