bash assign variable to another after operation - bash

I'm trying to print domain and topLeveldomain variables (example.com)
$line = example.com
domain =$line | cut -d. -f 1
topLeveldomain = $line | cut -d. -f 2
However when I try and echo $domain, it doesn't display desired value
test.sh: line 4: domain: command not found
test.sh: line 5: topLeveldomain: command not found

I suggest:
line="example.com"
domain=$(echo "$line" | cut -d. -f 1)
topLeveldomain=$(echo "$line" | cut -d. -f 2)

The right code for this should be:
line="example.com"
domain=$(echo "$line" | cut -d. -f 1)
topLeveldomain=$(echo "$line" | cut -d. -f 2)
Consider the right syntax of bash:
variable=value
(there are no blanks allowed)
if you want to use the content of the variable you have to add a leading $
e.g.
echo $variable

You don't need external tools for this, just do this in bash
$ string="example.com"
# print everything upto first de-limiter '.'
$ printf "${string%%.*}\n"
example
# print everything after first de-limiter '.'
$ printf "${string#*.}\n"
com

Remove spaces around =:
line=example.com # YES
line = example.com # NO
When you create a variable, do not prepend $ to the variable name:
line=example.com # YES
$line=example.com # NO
When using pipes, you need to pass standard output to the next command. Than means, you usually need to echo variables or cat files:
echo $line | cut -d. -f1 # YES
$line | cut -d. -f1 # NO
Use the $() syntax to get the output of a command into a variable:
new_variable=$(echo $line | cut -d. -f1) # YES
new_variable=echo $line | cut -d. -f1 # NO

I would rather use AWK:
domain="abc.def.hij.example.com"
awk -F. '{printf "TLD:%s\n2:%s\n3:%s\n", $NF, $(NF-1), $(NF-2)}' <<< "$domain"
Output
TLD:com
2:example
3:hij
In the command above, -F option specifies the field separator; NF is a built-in variable that keeps the number of input fields.
Issues with Your Code
The issues with your code are due to invalid syntax.
To set a variable in the shell, use
VARNAME="value"
Putting spaces around the equal sign will cause errors. It is a good
habit to quote content strings when assigning values to variables:
this will reduce the chance that you make errors.
Refer to the Bash Guide for Beginners.

this also works:
line="example.com"
domain=$(echo $line | cut -d. -f1)
toplevel=$(cut -d. -f2 <<<$line)
echo "domain name=" $domain
echo "Top Level=" $toplevel
You need to remove $ from line in the beginning, correct the spaces and echo $line in order to pipe the value to cut . Alternatively feed the cut with $line.

Related

How to increment a numerical value in properties file

I have a version.properties file as below:
#some comments
major=2
minor=16
patch=4
I want to increase the minor value by 1. so new value should be 16 +1 = 17.
So the updated file will be:
#some comments
major=2
minor=17
patch=4
Is it possible to achieve this through bash script?
Thanks in advance
You could use awk:
awk -F"=" 'BEGIN{OFS=FS} $1=="minor"{$2=$2+1}1' versions.properties
This awk script says:
Split each record by a an equal sign (-F"=")
Ensure that the output field separator OFS is equal to the incoming field separator FS (BEGIN{OFS=FS})
If the first field is the word "minor" ($1=="minor")
Then add 1 to the second field ({$2=$2+1})
Finally print the record back out 1.
You can redirect this to a temp file and then mv the temp back over the top of the original:
awk -F"=" 'BEGIN{OFS=FS} $1=="minor"{$2=$2+1}1' versions.properties > versions.properties.tmp && mv versions.properties.tmp versions.properties
You can also use this:
#! /bin/bash
LINE=$(cat version.properties | grep minor)
VAL=$(echo $LINE | cut -f 2 -d "=")
VAL=$(($VAL + 1))
NEW_LINE=$(echo minor=$VAL)
sed -e "s,$LINE,$NEW_LINE,g" -i version.properties
It fixes the issue without the need to use additional redirections and mv commands. Hope this helps :-)
Steps:
1- Get line number of your parameter (to use in replacement)
grep -n "minor" version.properties | cut -d: -f1
This shows "3" according to your version.properties file
We save it in a variable
line=$(grep -n "minor" version.properties | cut -d: -f1)
2- Get key=value
grep -n "minor" version.properties | cut -d: -f2
This shows minor=16 according to your version.properties file
We save it in a variable called string:
string=$(grep -n "minor" version.properties | cut -d: -f2)
3- Get version of this string : minor=16
version=$(echo $string | cut -d= -f2)
4- Increase version
newVersion=$(( version + 1))
5- Replace in original properties file using line number:
sed -i "$line c $key=$newVersion" version.properties
Finally this is a complete script , with key and file as parameters, so you could use it to increase any key like in any properties file, in any location :
key=$1
file=$2
line=$(grep -n "$key" $file | cut -d: -f1)
string=$(grep -n "$key" $file | cut -d: -f2)
# get version from string
version=$(echo $string | cut -d= -f2)
#increase version
newVersion=$(( version + 1))
#update file
sed -i "$line c $key=$newVersion" $file
Usage:
bash update_version.sh "patch" /server/files/version.properties
Note : keys in file must be unique.

exiting an IF statement after initial match bash scripting

I have a script which iterates through a file and finds matches in another file. How to I get the process to stop once I've found a match.
For example:
I take the first line in name.txt, and then try to find a match for it in file.txt.
name.txt:
7,7,FRESH,98,135,
65,10,OLD,56,45,
file.txt:
7,7,Dave,S
8,10,Frank,S
31,7,Gregg
45,5,Jake,S
Script:
while read line
do
name_id=`echo $line | cut -f1,2 -d ','`
identiferOne=`echo $name_id | cut -f1 -d ','`
identiferTwo=`echo $name_id | cut -f2 -d ','`
while IFS= read line
do
CHECK=`echo $line | cut -f4 -d','`
if [ $CHECK = "S" ]
then
symbolName=`echo $line | cut -f3 -d ','`
numberOne=`echo $line | awk -F',' '{print $1}'`
numberTwo=`echo $line | cut -f2 -d ','`
if [ "$numberOne" == $identiferOne ] && [ "$numberTwo" == $identifierTwo ]
then
echo "WE HAVE A MATCH with $symbolName"
break
fi
fi
done < /tmp/file.txt
done < /tmp/name.txt
My question is - how do I stop the script from iterating through file.txt once it has found an initial match, and then set that matched record into a variable, stop the if statement, then do some other stuff within the loop using that variable. I tried using break; but that exits the loop, which is not what I want.
You can tell grep different things:
Stop searching after the first match (option -m 1).
Read the searchkeys from a file (option -f file).
Pretend that the output of a command is a file (not really grep, bash helps here) with <(cmmnd).
Combining these will give you
grep -m1 -f <(cut -d"," -f1-2 name.txt) file.txt
Close, but not what you want. The substrings given by cut -d"," -f1-2 name.txt will match everywhere in the line, and you want to match the first two fields. Matching at the start of the line is done with ^, so we use sed to make strings like ^field1,field2 :
grep -m1 -f <(sed 's/\([^,]*,[^,]*,\).*/^\1/' name.txt) file.txt

Weird bash results using cut

I am trying to run this command:
./smstocurl SLASH2.911325850268888.911325850268896
smstocurl script:
#SLASH2.911325850268888.911325850268896
model=$(echo \&model=$1 | cut -d'.' -f 1)
echo $model
imea1=$(echo \&simImea1=$1 | cut -d'.' -f 2)
echo $imea1
imea2=$(echo \&simImea2=$1 | cut -d'.' -f 3)
echo $imea2
echo $model$imea1$imea2
Result Received
&model=SLASH2911325850268888911325850268896
Result Expected
&model=SLASH2&simImea1=911325850268888&simImea2=911325850268896
What am I missing here ?
You are cutting based on the dot .. In the first case your desired string contains the first string, the one containing &model, so then it is printed.
However, in the other cases you get the 2nd and 3rd blocks (-f2, -f3), so that the imea text gets cutted off.
Instead, I would use something like this:
while IFS="." read -r model imea1 imea2
do
printf "&model=%s&simImea1=%s&simImea2=%s\n" $model $imea1 $imea2
done <<< "$1"
Note the usage of printf and variables to have more control about what we are writing. Using a lot of escapes like in your echos can be risky.
Test
while IFS="." read -r model imea1 imea2; do printf "&model=%s&simImea1=%s&simImea2=%s\n" $model $imea1 $imea2
done <<< "SLASH2.911325850268888.911325850268896"
Returns:
&model=SLASH2&simImea1=911325850268888&simImea2=911325850268896
Alternatively, this sed makes it:
sed -r 's/^([^.]*)\.([^.]*)\.([^.]*)$/\&model=\1\&simImea1=\2\&simImea2=\3/' <<< "$1"
by catching each block of words separated by dots and printing back.
You can also use this way
Run:
./program SLASH2.911325850268888.911325850268896
Script:
#!/bin/bash
String=`echo $1 | sed "s/\./\&simImea1=/"`
String=`echo $String | sed "s/\./\&simImea2=/"`
echo "&model=$String
Output:
&model=SLASH2&simImea1=911325850268888&simImea2=911325850268896
awk way
awk -F. '{print "&model="$1"&simImea1="$2"&simImea2="$3}' <<< "SLASH2.911325850268888.911325850268896"
or
awk -F. '$0="&model="$1"&simImea1="$2"&simImea2="$3' <<< "SLASH2.911325850268888.911325850268896"
output
&model=SLASH2&simImea1=911325850268888&simImea2=911325850268896

Using values of variables in on-the-spot shell commands (using ``)

I have a shell script that for-loops over input to get a number and string. If I want to test the number in the loop, can I cut the looped-over variable to get the number? For example, something like:
for line in input
do
num=`cut -f1 $line`
...
done
If not, how else can I accomplish this?
Instead of:
num=`cut -f1 $line`
You can do:
num=$(echo "$line" | cut -f1)
OR else using awk:
num=$(awk '{print $1}' <<< $line)
OR using pure BASH:
num=${line%% *}
Your command cut -f1 $line will try to cut first column from a file named as $line.
Is this what you want instead ?
while read -r number str
do
echo $number;
echo $str;
done < input

Shell script: how to read only a portion of text from a variable

I'm developing a little script using ash shell (not bash).
Now i have a variable with the following composition:
VARIABLE = "number string status"
where number could be any number (actually between 1 and 18 but in the future that number could be higher) the string is a name and status is or on or off
The name usually is only lowercase letter.
Now my problem is to read only the string content in the variable, removing the number and the status.
How i can obtain that?
Two ways; one is to leverage $IFS and use a while loop - this will work for a single line quite happily - as:
echo "Part1 Part2 Part3" | while read a b c
do
echo $a
done
alternatively, use cut as follows:
a=`echo $var | cut -d' ' -f2`
echo $a
How about using cut?
name=$(echo "$variable" | cut -d " " -f 2)
UPDATE
Apparently, Ash doesn't understand $(...). Hopefully you can do this instead:
name=`echo "$variable" | cut -d " " -f 2`
How about :
name=$(echo "$variable" | awk '{print $2}')
#!/bin/sh
myvar="word1 word2 word3 wordX"
set -- $myvar
echo ${15} # outputs word 15

Resources