Setting variables in shell script by running commands - shell

>cat /tmp/list1
john
jack
>cat /tmp/list2
smith
taylor
It is guaranteed that list1 and list2 will have equal number of lines.
f(){
i=1
while read line
do
var1 = `sed -n '$ip' /tmp/list1`
var2 = `sed -n '$ip' /tmp/list2`
echo $i,$var1,$var2
i=`expr $i+1`
echo $i,$var1,$var2
done < $INFILE
}
So output of f() should be:
1,john,smith
2,jack,taylor
But getting
1,p,p
1+1,p,p
If i replace following:
var1 = `sed -n '$ip' /tmp/list1`
var2 = `sed -n '$ip' /tmp/list2`
with this:
var1=`head -$i /tmp/vip_list|tail -1`
var2=`head -$i /tmp/lb_list|tail -1`
Then output:
1,john,smith
1,john,smith

If you can use paste and awk command, you can achieve the same with a one-liner:
paste -d, /tmp/list1 /tmp/list2 | awk '{print NR "," $0}'
Replace the while script with this line :)

the $ip is the problem there making ip the name of the variable, you should use ${i}p instead letting the shell know that the variable is i not ip, your code should look like
var1=`sed -n "${i}p" /tmp/list1`
var2=`sed -n "${i}p" /tmp/list2`

Related

Get the third element of a line into a file with script shell

I'm doing a script shell and I want to read data inside a file. In the file, I have something like :
/path/to/file1 something 0
/path/to/file2 something2 1
/path/to/file3 something3 2
What I want is to get the third element of the line but I don't know how to do it.
In my code, I have:
while read line;
do
//must echo the third element of the line
done < file | sort -n -k 2 -t " "
I already tried with awk but it didn't work.
How should I do please ?
This works if fields are separated by space:
$ echo 'foo bar baz' | cut --delimiter=' ' --fields=3
baz
This works for most whitespace separators:
$ echo 'foo bar baz' | awk '{print $3}'
baz
you can try something like this;
while read line;
do
path=$(echo $line | awk '{print $1}')
secondColumn=$(echo $line | awk '{print $2}')
thirdColumn=$(echo $line | awk '{print $3}')
echo $path
echo $secondColumn
echo $thirdColumn
done < test

print line without the first word into a variable

This is my code
title=""
line=""
fname=$1
numoflines=$(wc -l < $fname)
for ((i=2 ; i<=$numoflines ; i++))
do
...
done
In the for loop i want to print the first word of every line into $title
and the rest of the line without the first word into $line
(using bash)
tnx
I am assuming that by print to a variable you mean add the contents of each line to the variable. To do this, you can use the bash built-in function read:
while read -r t l; do title+="$t"; line+="$l"; done < "$fname"
This will add the first word of every line to $title and the rest of the line to $line.
You can do some like this:
echo "$fname"
This is my line.
My cat is green.
title=$(awk '{print $1}' <<< "$fname")
line=$(awk '{$1="";sub(/^ /,"")}1' <<< "$fname")
echo "$title"
This
My
echo "$line"
is my line.
cat is green.
Alternative approach using the cut command:
file="./myfile.txt"
title=$(cut -f1 -d ' ' "$file")
line=$(cut -f2- -d ' ' "$file")
#check print
pr -tm <(echo -e "TITLES\n$title") <(echo -e "LINES\n$line")
for the next myfile.txt
My cat is green.
Green cats are strange.
prints
TITLES LINES
My cat is green.
Green cats are strange.
do
Tempo="$( sed -n "${i} {s/^[[:blank:]]*\([^[:blank:]]*\)[[:blank:]]*\(.*\)/title='\1';line='\2'/p;q;}" ${fname} )"
eval "${Tempo}"
done
# or
do
sed -n "${i} {p;q;}" | read Line Title
# but this does not keep content available on each OS/shell
done

Splitting a text in Unix

I am writing a simple script that splits a variable that holds some text by using below code:
#!/bin/sh
SAMPLE_TEXT=hello.world.testing
echo $SAMPLE_TEXT
OUT_VALUE=$SAMPLE_TEXT | cut -d'.' -f1
echo output is $OUT_VALUE
I am expecting output as output is hello but when I run this program then I am getting output as output is. Please let me know where I am doing mistake?
To evaluate a command and store it into a variable, use var=$(command).
All together, your code works like this:
SAMPLE_TEXT="hello.world.testing"
echo "$SAMPLE_TEXT"
OUT_VALUE=$(echo "$SAMPLE_TEXT" | cut -d'.' -f1)
# OUT_VALUE=$(cut -d'.' -f1 <<< "$SAMPLE_TEXT") <--- alternatively
echo "output is $OUT_VALUE"
Also, note I am adding quotes all around. It is a good practice that will help you in general.
Other approaches:
$ sed -r 's/([^\.]*).*/\1/g' <<< "$SAMPLE_TEXT"
hello
$ awk -F. '{print $1}' <<< "$SAMPLE_TEXT"
hello
$ echo "${SAMPLE_TEXT%%.*}"
hello
The answer by fedorqui is the correct answer. Just adding another approach...
$ SAMPLE_TEXT=hello.world.testing
$ IFS=. read OUT_VALUE _ <<< "$SAMPLE_TEXT"
$ echo output is $OUT_VALUE
output is hello
Just to expand on #anishane's comment to his own answer:
$ SAMPLE_TEXT="hello world.this is.a test string"
$ IFS=. read -ra words <<< "$SAMPLE_TEXT"
$ printf "%s\n" "${words[#]}"
hello world
this is
a test string
$ for idx in "${!words[#]}"; do printf "%d\t%s\n" $idx "${words[idx]}"; done
0 hello world
1 this is
2 a test string

how to insert new line in bash shell for variable?

I have two variables var1 and var2. The contents of each variables come from bash shell grep command.
echo $var1 prints
123 465 326 8080
echo $var2 prints
sila kiran hinal juku
Now I want to print the above into following formats in Linux bash shell
123 sila
465 kiran
326 hinal
8080 juku
So how can I print this way in bash shell??
What about?
$ paste -d" " <(echo $var1 | xargs -n1) <(echo $var2 | xargs -n1)
We can even skip the echo:
$ paste -d" " <(xargs -n1 <<< $var1) <(xargs -n1 <<< $var2)
Without a loop:
$ var1="123 465 326 8080"
$ var2="sila kiran hinal juku"
$ var1=($var1); var2=($var2)
$ saveIFS=IFS
$ IFS=$'\n'
$ paste <(echo "${a[*]}") <(echo "${b[*]}"
$ IFS=$saveIFS
With a loop (assumes that the two strings have the same number of words):
$ var1="123 465 326 8080"
$ var2="sila kiran hinal juku"
$ var2=($var2)
$ for s in $var1; do echo $s ${vars[i++]}; done
Using file descriptors and a while-loop:
var1="123 465 326 8080"
var2="sila kiran hinal juku"
IFS=" " exec 7< <(printf "%s\n" $var1) 8< <(printf "%s\n" $var2)
while read -u7 f1 && read -u8 f2; do
echo "$f1 $f2"
done
I'd store them into arrays $var1[] and $var2[] instead of a some long string and then iterate through the arrays with a loop to output it the way you want.
If you don't want ot use arrays, you could use awk and the iterator from a loop to print out the names one at a time.
join <(echo $var1 | sed -r 's/ +/\n/g' | cat -n) <(echo $var2 | sed -r 's/ +/\n/g' | cat -n) -o "1.2,2.2"

Redirect output to a bash array

I have a file containing the string
ipAddress=10.78.90.137;10.78.90.149
I'd like to place these two IP addresses in a bash array. To achieve that I tried the following:
n=$(grep -i ipaddress /opt/ipfile | cut -d'=' -f2 | tr ';' ' ')
This results in extracting the values alright but for some reason the size of the array is returned as 1 and I notice that both the values are identified as the first element in the array. That is
echo ${n[0]}
returns
10.78.90.137 10.78.90.149
How do I fix this?
Thanks for the help!
do you really need an array
bash
$ ipAddress="10.78.90.137;10.78.90.149"
$ IFS=";"
$ set -- $ipAddress
$ echo $1
10.78.90.137
$ echo $2
10.78.90.149
$ unset IFS
$ echo $# #this is "array"
if you want to put into array
$ a=( $# )
$ echo ${a[0]}
10.78.90.137
$ echo ${a[1]}
10.78.90.149
#OP, regarding your method: set your IFS to a space
$ IFS=" "
$ n=( $(grep -i ipaddress file | cut -d'=' -f2 | tr ';' ' ' | sed 's/"//g' ) )
$ echo ${n[1]}
10.78.90.149
$ echo ${n[0]}
10.78.90.137
$ unset IFS
Also, there is no need to use so many tools. you can just use awk, or simply the bash shell
#!/bin/bash
declare -a arr
while IFS="=" read -r caption addresses
do
case "$caption" in
ipAddress*)
addresses=${addresses//[\"]/}
arr=( ${arr[#]} ${addresses//;/ } )
esac
done < "file"
echo ${arr[#]}
output
$ more file
foo
bar
ipAddress="10.78.91.138;10.78.90.150;10.77.1.101"
foo1
ipAddress="10.78.90.137;10.78.90.149"
bar1
$./shell.sh
10.78.91.138 10.78.90.150 10.77.1.101 10.78.90.137 10.78.90.149
gawk
$ n=( $(gawk -F"=" '/ipAddress/{gsub(/\"/,"",$2);gsub(/;/," ",$2) ;printf $2" "}' file) )
$ echo ${n[#]}
10.78.91.138 10.78.90.150 10.77.1.101 10.78.90.137 10.78.90.149
This one works:
n=(`grep -i ipaddress filename | cut -d"=" -f2 | tr ';' ' '`)
EDIT: (improved, nestable version as per Dennis)
n=($(grep -i ipaddress filename | cut -d"=" -f2 | tr ';' ' '))
A variation on a theme:
$ line=$(grep -i ipaddress /opt/ipfile)
$ saveIFS="$IFS" # always save it and put it back to be safe
$ IFS="=;"
$ n=($line)
$ IFS="$saveIFS"
$ echo ${n[0]}
ipAddress
$ echo ${n[1]}
10.78.90.137
$ echo ${n[2]}
10.78.90.149
If the file has no other contents, you may not need the grep and you could read in the whole file.
$ saveIFS="$IFS"
$ IFS="=;"
$ n=$(</opt/ipfile)
$ IFS="$saveIFS"
A Perl solution:
n=($(perl -ne 's/ipAddress=(.*);/$1 / && print' filename))
which tests for and removes the unwanted characters in one operation.
You can do this by using IFS in bash.
First read the first line from file.
Seoncd convert that to an array with = as delimeter.
Third convert the value to an array with ; as delimeter.
Thats it !!!
#!/bin/bash
IFS='\n' read -r lstr < "a.txt"
IFS='=' read -r -a lstr_arr <<< $lstr
IFS=';' read -r -a ip_arr <<< ${lstr_arr[1]}
echo ${ip_arr[0]}
echo ${ip_arr[1]}

Resources