bash,shell, unexpected token done - bash

here is my code:
echo -n "Enter 3 parameters in format file-num1-num2: "
str=""
while read param
do
echo $param >|temp
fname=$(cut -d"-" -f1 temp)
num1=$(cut -d"-" -f2 temp)
num2=$(cut -d"-" -f3 temp)
range=$num1"-"$num2
head -$num3 $fname >|temp
tail -$num1 temp >|temp
st=$fname"-"$(wc -c <temp)
str=$str" "$st"-"$range
echo $(wc -c <temp) >>temp2
echo -n "Enter 3 parameters in format file-num1-num2: "
done
sort temp2 >|temp
c=$(wc -l temp)
c2=0
while [ $c2 -lt $c ]
do
((c2++))
head -$c2 temp >|temp3
tail -1 temp3 >|temp3
num=$(cat temp3)
for x in $str
do
echo $x >| temp4
fname=$(cut -d"-" -f1 temp4)
ran=$(cut -d"-" -f2 temp4)
sh=$(cut -d"-" -f3 temp4)
if [ $ran -eq $num ]
then
echo "The size of file $fname in lines $sh is: $num"
done
done
rm temp
rm temp2
rm temp3
rm temp4
ok so the problem is when i run the script i get this error:
./P4.4: line 36: syntax error near unexpected token `done'
./P4.4: line 36: `done'
and when i run it for some reason the first loop gets stuck and i need to press ctrl^d to keep it going and do it two time to get out of the loop
and this is what the code is supposed to do:
input:
g-5-7
f-2-4
output:
The size of file f in lines 2-4 is: 16
The size of file g in lines 5-7 is: 10
file g:
12
34
56
78
910
ab
wz
file f:
aa
bb c
dd ef
gh x
ttt

if [ $ran -eq $num ]
then
echo "The size of file $fname in lines $sh is: $num"
done
The if there is missing a fi.

Related

Issue with Bash variables

I'm trying to make a code for finding the number and type of atoms from a file.
The file B.txt has few names of the atoms in it and is read to go into the specific atom directory. The file input has the values of the positions and atom types in it. But I cannot store the name of atom as atom_1, atom_2, atom_3 etc..
If I change the atom_$i to atom, then the code works perfectly.
I expect the output to be atom_1=X,numberofatoms_1=100, atom_2=Y, numberofatoms_2=200 etc and so on.
The error is something like:
2(total number of types of atoms)
bash: atom_1=x: command not found
cd ~/A/
cat ~/A/B.txt | while read line
do
cd folder_"$line"
sed -n 6p input> temp1.txt
sed -n 7p input > temp2.txt
atoms= wc -w < temp1.txt > junk
#echo ${atoms}
typeset -i atoms=$(cat junk)
i=1
numberofatoms=0
echo ${atoms}
while [ $i -le $atoms ]
do
ptri=$( echo "scale=2; $i" | bc)
atom="$(cat temp1.txt | sed -n '1p'| cut -d' ' -f$ptri)" > junk
echo $atom
# next section is the code for counting the total number of atomsin the system
noa=$(cat temp2.txt | sed -n '1p'| cut -d' ' -f$ptri)
numberofatoms_$i=$(( $numberofatoms + $noa ))
i=`expr $i + 1`
done
echo "number of atoms = " $numberofatoms
cd ..
rm junk
rm temp1
rm temp2
done

Bash Shell Script errors: ambiguous redirect and unary operator expected

I'm totally new to writing code with shell script.
This is my code:
#!/bin/bash
echo -n "Output to $2 "
# set counter
count=1
# zap output file
> $2
# Loop
while [ $count -le $1 ]
do
# generate some random text
randomnumber=`od -A n -t d -N 1 /dev/urandom`
randomtext=`cat /dev/urandom | tr -cd "[:alnum:]" | head -c $randomnumber`
# generate a random number
randomnumber=`od -A n -t d -N 1 /dev/urandom`
# output to file
echo "$count,$randomtext,$randomnumber" | sed -e "s: *::g" >> $2
# increment counter
count=$(($count + 1))
if [ $(($count % 500)) -eq 0 ]
then
echo -n "." fi
done
echo " Output complete"
And this is my error:
Line 2: ambiguous redirect and Line 14: unary operator expected.
Can anybody help me to understand why I having that error?
As #GlennJackman points out, the lines are not matching the code, hence I am guessing the following:
The ambiguous redirection is on line 6: To truncate a file, you
should use truncate -s0 $2
For the unary operator error, I bet on line 21: either put a linefeed
or a semicolon ; before fi
Try the following:
#!/bin/bash
echo -n "Output to $2 "
# set counter
count=1
# zap output file
truncate -s0 $2
# Loop
while [ $count -le $1 ]
do
# generate some random text
randomnumber=`od -A n -t d -N 1 /dev/urandom`
randomtext=`cat /dev/urandom | tr -cd "[:alnum:]" | head -c $randomnumber`
# generate a random number
randomnumber=`od -A n -t d -N 1 /dev/urandom`
# output to file
echo "$count,$randomtext,$randomnumber" | sed -e "s: *::g" >> $2
# increment counter
count=$(($count + 1))
if [ $(($count % 500)) -eq 0 ]
then
echo -n "."
fi
done
echo " Output complete"

Grep command in array

For a homework assignment I have to Take the results from the grep command, and write out up to the first 5 of them, numbering them from 1 to 5. (Print the number, then a space, then the line from grep.) If there are no lines, print a message saying so. So far I managed to store the grep command in an array but this is where I've gotten stuck: Can anyone provide guidance as to how to proceed in printing this as stated above
pattern="*.c"
fileList=$(grep -l "main" $pattern)
IFS=$"\n"
declare -a array
array=$fileList
for x in "${array[#]}"; do
echo "$x"
done
you can grep options -c and -l
pattern="*.c"
searchPattern="main"
counter=1
while read -r line ; do
IFS=':' read -r -a lineInfo <<< "$line"
if [[ $counter > 5 ]]; then
exit 1
fi
if [[ ${lineInfo[1]} > 0 ]]; then
numsOfLine=""
while read -r fileline ; do
IFS=':' read -r -a fileLineInfo <<< "$fileline"
numsOfLine="$numsOfLine ${fileLineInfo[0]} "
done < <(grep -n $searchPattern ${lineInfo[0]})
echo "$counter ${lineInfo[0]} match on lines: $numsOfLine"
let "counter += 1"
else
echo "${lineInfo[0]} no match lines"
fi
done < <(grep -c $searchPattern $pattern)
If you're only allowed to use grep and bash(?):
pattern="*.c"
fileList=($(grep -l "main" $pattern))
if test ${#fileList[#]} = 0 ; then
echo "No results"
else
n=0
while test $n -lt ${#fileList[#]} -a $n -lt 5 ; do
i=$n
n=$(( n + 1 ))
echo "$n ${fileList[$i]}"
done
fi
If you are allowed to use commands in addition to grep, you can pipe the results through nl to add line numbers, then head to limit the results to the first 5 lines, then a second grep to test if there were any lines. For example:
if ! grep -l "main" $pattern | \
nl -s ' ' | sed -e 's/^ *//' | \
head -n 5 | grep '' ; then
echo "No results"
fi

how can i echo a line once , then the rest keep them the way they are in unix bash?

I have the following comment:
(for i in 'cut -d "," -f1 file.csv | uniq`; do var =`grep -c $i file.csv';if (($var > 1 )); then echo " you have the following repeated numbers" $i ; fi ; done)
The output that i get is : You have the following repeated numbers 455
You have the following repeated numbers 879
You have the following repeated numbers 741
what I want is the following output:
you have the following repeated numbers:
455
879
741
Try moving the echo of the header line before the for-loop :
(echo " you have the following repeated numbers"; for i in 'cut -d "," -f1 file.csv | uniq`; do var =`grep -c $i file.csv';if (($var > 1 )); then echo $i ; fi ; done)
Or only print the header once :
(header=" you have the following repeated numbers\n"; for i in 'cut -d "," -f1 file.csv | uniq`; do var =`grep -c $i file.csv';if (($var > 1 )); then echo -e $header$i ; header=""; fi ; done)
Well, here's what I came to:
1) generated input for testing
for x in {1..35},aa,bb ; do echo $x ; done > file.csv
for x in {21..48},aa,bb ; do echo $x ; done >> file.csv
for x in {32..63},aa,bb ; do echo $x ; done >> file.csv
unsort file.csv > new.txt ; mv new.txt file.csv
2) your line ( corrected syntax errors)
dtpwmbp:~ pwadas$ for i in $(cut -d "," -f1 file.csv | uniq);
do var=`grep -c $i file.csv`; if [ "$var" -ge 1 ] ;
then echo " you have the following repeated numbers" $i ; fi ; done | head -n 10
you have the following repeated numbers 8
you have the following repeated numbers 41
you have the following repeated numbers 18
you have the following repeated numbers 34
you have the following repeated numbers 3
you have the following repeated numbers 53
you have the following repeated numbers 32
you have the following repeated numbers 33
you have the following repeated numbers 19
you have the following repeated numbers 7
dtpwmbp:~ pwadas$
3) my line:
dtpwmbp:~ pwadas$ echo "you have the following repeated numbers:";
for i in $(cut -d "," -f1 file.csv | uniq); do var=`grep -c $i file.csv`;
if [ "$var" -ge 1 ] ; then echo $i ; fi ; done | head -n 10
you have the following repeated numbers:
8
41
18
34
3
53
32
33
19
7
dtpwmbp:~ pwadas$
I added quotes, changed if() to [..] expression, and finally moved description sentence out of loop. Number of occurences tested is digit near "-ge" condition. If it is "1", then numbers which appear once or more are printed. Note, that in this expression, if file contains e.g. numbers
8
12
48
then "8" is listed in output as appearing twice. with "-ge 2", if no digits appear more than once, no output (except heading) is printed.

count words in a file without using wc

Working in a shell script here, trying to count the number of words/characters/lines in a file without using the wc command. I can get the file broken into lines and count those easy enough, but I'm struggling here to get the words and the characters.
#define word_count function
count_stuff(){
c=0
w=0
l=0
local f="$1"
while read Line
do
l=`expr $line + 1`
# now that I have a line I want to break it into words and characters???
done < "$f"
echo "Number characters: $chars"
echo "Number words: $words"
echo "Number lines: $line"
}
As for characters, try this (adjust echo "test" to where you get your output from):
expr `echo "test" | sed "s/./ + 1/g;s/^/0/"`
As for lines, try this:
expr `echo -e "test\ntest\ntest" | sed "s/^.*$/./" | tr -d "\n" | sed "s/./ + 1/g;s/^/0/"`
===
As for your code, you want something like this to count words (if you want to go at it completely raw):
while read line ; do
set $line ;
while true ; do
[ -z $1 ] && break
l=`expr $l + 1`
shift ;
done ;
done
You can do this with the following Bash shell script:
count=0
for var in `cat $1`
do
count=`echo $count+1 | bc`
done
echo $count

Resources