get query string in array with bash - bash

I have a sqlite with a table with 2 columns. I would like to get the two values of the columns in every variable or in an array. For instance:
table A
COLUMN A COLUMN B
credit and risk David
nothing susan
.....
and I would like to obtain: Variable A="credit and risk" and variable B="David" then Variable A ="nothing" and variable B= "susan" and so on.
I'm trying with these code but if the column A have space I can't get the string complete, for example I obtain "credit" only. My code:
valores=($(sqlite3 alcampo.db "select DESCRIPTION, URL FROM SUBCATEGORYS"))
cnt=${#valores[#]}
echo "cuenta es ... $cnt"
for (( i=0 ; i<cnt ; i++ ))
do
echo "Record No. $i: ${valores[$i]}"
fieldA=${valores[0]}
echo "campo a es ... $fieldA"
fieldB=${valores[1]}
echo "campo B es ... $fieldB"
done
Could you help me please? Thanks

There might be better ways to get this done.
It sounds like you don't want to keep the variables after you echo them.
while read line; do
fieldA=$( echo "$line" | sed -n "s/\(.*\)\s\{2,\}.*/\1/p" )
fieldB=$( echo "$line" | sed -n "s/.*\s\{2,\}\(.*\)/\1/p" )
echo "campo A es ... ${fieldA}"
echo "campo B es ... ${fieldB}"
done < <(sqlite3 alcampo.db "select DESCRIPTION, URL FROM SUBCATEGORYS")
This will ready your command "sqlite3 ..." directly into the while loop. The while loop will assign each line to the variable "$line".
We then echo the $line variable and sed it to grab the information we want. The sed is based on having 2 or more spaces between the columns...it was the only way I could think to delimit the data based off of what you posted.
$( ) -- command substitution
-n -- don't print
s -- substitute
\( -- begin capture group 1
.* -- match anything
\) -- end capture group 1
\s{2,} -- 2 or more white-space characters
.* -- anything else
\1 -- output capture group 1
p -- print it
I hope this helps. Let me know.

Related

Count columns with bash

I need to find a way to count columns from a file OR stdin without using anything except pure bash. What I have so far...
input="${1:-/dev/stdin}"
rows=0
while read -r myLine
do
a=($myLine)
cols=(${#a[*]})
rows=`expr $rows + 1`
done < $input
echo -e "$rows $cols"
I'm counting both rows and columns. Right now, my column count only works for files, not stdin.
Any advice?
Im running the following commands
echo -e "1\t2\n3\t4" > m1, ./matrix m1
echo -e "1\t2\n3\t4" | matrix
I would advise awk for this task, but if you need bash, you could use arrays:
let c=0
while read -r myLine; do
a=($myLine)
echo "Line $((++c)) has ${#a[*]} columns"
done < file
The array a is filled with the content of the line read by the read function.
The number of columns is the length of the array a.
Note this script assumes the input field separator IFS to be unset (and as a consequence to default to <space><tab><newline> for the read command).

Create a loop for 3 different variables to output all possible combinations

So lets say i have 3 lines of code
ABC
123
!##
How do i create a for loop to output the number of ways to piece them together?
E.G ABC123!##, ABC!##123, 123ABC!##$
here is my current line of code
#!/bin/bash
alphabet='ABC' numbers='123' special='!##'
for name in $alphabet$numbers$special
do
echo $name
done
echo done
alphabet='ABC' numbers='123' special='!##'
for name1 in $alphabet $numbers $special
#on 1st iteration, name1's value will be ABC, 2nd 123 ...
do
for name2 in $alphabet $numbers $special
do
for name3 in $alphabet $numbers $special
do
#here we ensure that we want strings only as combination of that three strings
if [ $name1 != $name2 -a $name2 != $name3 ]
then
echo $name1$name2$name3
fi
done
done
done
if you want also to print strings, like 123123123 and ABCABCABC, remove if condition
You can also do it without a loop at all using brace expansion (but you lose the ability to exclude, e.g. ABCABCABC). For example:
#!/bin/bash
alpha='ABC'
num='123'
spec='!##'
printf "%s\n" {$alpha,$num,$spec}{$alpha,$num,$spec}{$alpha,$num,$spec}
Example Use/Output
$ bash permute_brace_exp.sh
ABCABCABC
ABCABC123
ABCABC!##
ABC123ABC
ABC123123
ABC123!##
ABC!##ABC
ABC!##123
ABC!##!##
123ABCABC
123ABC123
123ABC!##
123123ABC
123123123
123123!##
123!##ABC
123!##123
123!##!##
!##ABCABC
!##ABC123
!##ABC!##
!##123ABC
!##123123
!##123!##
!##!##ABC
!##!##123
!##!##!##

Changing words in text files using multiple dictionaries

I have a bunch of files which need to be translated using custom dictionaries. Each file contains a line indicating which dictionary to use. Here's an example:
*A:
!
=1
*>A_intro
1r
=2
1r
=3
1r
=4
1r
=5
2A:maj
*-
In the file above, *A: indicates to use dictA.
I can translate this part easily using the following syntax:
sed -f dictA < myfile
My problem is that some files require a change of dictionary half way in the text. For example:
*B:
1B:maj
2E:maj/5
2B:maj
2E:maj/5
*C:
2F:maj/5
2C:maj
2F:maj/5
2C:maj
*-
I would like to write a script to automate the translation process. Using this example, I would like the script to read the first line, select dictB, use dictB to translate each line until it reads *C:, select dictC, and then keep going.
Thanks #Cyrus. That was useful. Here's what I ended up doing.
#!/bin/sh
key="sedDictNull.txt"
while read -r line || [ -n "$line" ] ## Makes sure that the last line is read. See http://stackoverflow.com/questions/12916352/shell-script-read-missing-last-line
do
if [[ $line =~ ^\*[Aa]:$ ]]
then
key="sedDictA.txt"
elif [[ $line =~ ^\*[Aa]#:$ ]]
then
key="sedDictA#.txt"
fi
echo "$line" | sed -f $key
done < $1
I assume your "dictionaries" are really sed scripts that search and replace, like this:
s/2C/nothing/;
s/2B/something/;
You could reorganize these scripts into sections, like this:
/^\*B:/, /^\*[^B]/ {
s/1B/whatever/;
s/2B/something/;
}
/^\*C:/, /^\*[^C]/ {
s/2C/nothing/;
s/2B/something/;
}
And, of course, you could do that on the fly:
for dict in B C
do echo "/^\\*$dict:/, /^\\*[^$dict]/ {"
cat dict.$dict
echo "}"
done | sed -f- dict.in

Splitting the first word from each record and push that in to array

inputfile : records.txt
100,Surender,CTS
101,Kumar,TCS
102,Raja,CTS
103,Vijay,TCS
I want to store the first column from each record and store that in to array .
I wrote the below script
id_array=();
while read -a my_line ;
do
id_array+=(${my_line[0]})
done < /home/user/surender/linux/inputfiles/records.txt;
echo ${id_array[0]}
echo ${id_array[1]}
echo ${id_array[2]}
echo ${id_array[3]}
My expected output is
100
101
102
103
But as Per above code i get the below output
100,Surender,CTS
101,Kumar,TCS
102,Raja,CTS
103,Vijay,TCS
I dont know where to specify the respective delimiter(comma) in above script.
Need some Help on this..
Replace the line:
while read -a my_line ;
With:
while IFS=',' read -a my_line ;
That will split the lines into an array using the delimiter ,.
There are many methods to get the first field. Cut is very intuitive, although this is probably not the most efficient code:
id_array+=(echo $my_line | cut -d ',' -f 1)
explanation:
-d ',' : delimiter is ,
-f 1 : take the first field
in a related answer you can find a more efficient way, setting the internal field separator (IFS) to ,...

Read rest of while loop output

I want to run a while loop from output I get from MySQL, but my output is being cut off.
Example output I get from MySQL is:
123 nfs://192.168.1.100/full/Some.file.1.txt
124 nfs://192.168.1.100/full/A second file 2.txt
My loop looks like so:
mysql -uuser -ppass queue -ss -e 'select id,path from queue where status = 0' | while read a b c
do
echo $a
echo $b
done
The result for $b cuts off after nfs://192.168.1.100/full/A.
How can I have it output the whole sentence?
Your second filename contains spaces, so that is where the field is cut off.
Since it is the last field of the output, you can just skip field c:
mysql -uuser -ppass queue -ss -e 'select id,path from queue where status = 0' | while read a b
do
echo $a
echo $b
done
The last field in read will have all remaining fields.
Problem is that you are reading each line into 3 variables using:
read a b c
And since your input line also contains a whitespace e.g.
124 nfs://192.168.1.100/full/A second file 2.txt
with the default IFS it is setting 3 variables as:
a=124
b=nfs://192.168.1.100/full/A
c=second file 2.txt
Since c is the last parameter in read it is reading rest of the line in c.
To fix your script you can just do:
read a b

Resources