while read line
do
echo "$line"
i=0;
rm -rf b.txt
while [[ $i -lt $line ]]
do
i=`expr $i + 1`
echo "$i " >> b.txt
done
a=`cat b.txt`
for i in $a;
do
echo "Hari $i \c"
read input
done
done < 5.txt
Say 5.txt has the value:
2
3
This script needs to place the cursor inside the for loop, but the script is continuously executing and ending. Can you please help me over this?
Assuming 5.txt consists of:
2
3
The script outputs:
2
Hari 1 \c
Hari 2 \c
...and quits.
The script won't prompt for input after outputting Hari 1 \c because all the input is coming from 5.txt. On the first pass $input would be set to 3, (the 2nd line of 5.txt). On the second pass, the input would be an EOF, in which case read gives up, much like how this outputs nothing:
read -p "Enter a number" n < /dev/null
This would work:
for i in `cat 5.txt` ; do \
echo $i ; for f in `seq $i` ; do read -p "Hari $f \c: " input ; done ; \
done
Note also that $input is never used for anything.
Related
I have written this code to imitate tail command without using inbuilt command and it is giving error in for loop though syntax is correct!
I am not able to figure it out where actually the error is?
Also Expected output:
It should print last n number of lines from the file.
n is scanned from user.
#!/bin/sh echo -n "Enter file name: " read file_name echo -n "Enter number of lines: " read n touch $file_name str="end" temp="temp" echo "Start entering data of file and write end for stopping: " while [ 1 ] do read string touch $temp echo $string > $temp grep -w "$str" $temp if [ $? -eq 0 ] then break else cat $temp >> $file_name fi done rm $temp echo "---------------------------------------------------------" total_lines= wc -l < $file_name echo $total_lines a=expr $total_lines - $n exec < $file_name for ((i=$a;i<$total_lines;i++ )) do read a1 echo $a1 done
My problem is pretty simple. I have :
a=$(echo "lol")
for i in {1..3};
do
echo $a && echo $i ;
done
I get :
lol
1
lol
2
lol
3
I would like to print only once the variable a at the beginning of the output , to get :
lol
1
2
3
Any idea?
You don't need a loop at all
a=$(echo "lol") # Not sure why poster wrote this rater than a=lol
printf %s\\n "$a" {1..3}
I suggest:
#!/bin/bash
a="lol"$'\n' # append newline
for i in {1..3}
do
echo -e "$a$i" # -e: enable interpretation of escape sequences
unset a
done
Or replace in your question
echo $a && echo $i ;
with
[[ "$i" == "1" ]] && echo "$a"
echo "$i"
See: help echo and help unset
Move the echo outside of the for loop
a=$(echo "lol")
echo $a
for i in {1..3}; do
echo $i;
done
or:
echo "lol"
for i in {1..3}; do
echo $i;
done
test run in shell
I have file1:
A
B
C
D
I have file2:
B
C
I want to use a while read loop to go through both files compare them and print out the line number of file1 for any matching lines.
COUNT=0
while read line
do
flag = 0
while read line2
do
COUNT=$(( $COUNT + 1 ))
if ( "$line" = "$line2" )
then
flag = 1
fi
done < file1
if ( flag -eq 1 )
then
echo $COUNT > file3
fi
done < file2
However I get an error: B command not found
Please could someone let me know where I have gone wrong. Thanks.
There are quite a lot of errors in this code, but to answer the question, the reason you are getting B command not found is because........ we use [] rather than () in bash.
other errors include:
COUNT=0
while read line
do
flag=0 # no space between flag and =
while read line2
do
COUNT=$(( $COUNT + 1 ))
echo $line
echo $line2
if [ "_$line" = "_$line2" ]
then
flag=1 #no space again
fi
done < file1
if [ $flag -eq 1 ] # use $flag rather than flag
then
echo $COUNT > file3
fi
done < file2
You could also achieve what you are looking for using grep -c like this:
#!/bin/bash
# Clean file3
>file3
while read line; do
COUNT=$(grep -c "^$line$" file2)
if [ $COUNT -ge 1 ]; then
$COUNT >> file3
fi
done < file1
grep -c prints the number of times an expression matches the file content.
My script is to ask for input 1 upper case at a time and end with 0 invalid input will need to be displayed and display the first valid upper letter.
#! /bin/sh
count=0
until [[ $n =~ 0 ]]; do
echo Inputs:
read n
if [[ $n =~ ^[A-Z]$ ]]; then
count=`expr $count + 1`
echo $n | sort > out.txt
fi
done
echo The total number of valid input letters:
echo $count
echo " "
echo The first valid input:
head -n 1 /filepath/out.txt
Output:
Inputs:
B
Inputs:
A
Inputs:
C
Inputs:
0
The total number of valid input letters:
3
The first valid input:
C
Question: It should result in A.
Any help will be appreciated.
This line:
echo $n | sort > out.txt
always zaps the file out.txt with just the latest input. Maybe you should use:
cp /dev/null out.txt # Before the loop
echo $n | sort -o out.txt out.txt -
The cp command creates an empty file. The sort command reads the existing file out.txt and its standard input (the new line), sorts the result and writes it out over out.txt.
This is OK for short inputs; it isn't very efficient if it needs to scale to thousands of lines.
Also, in Bash, you don't need to use expr for arithmetic:
((count++))
Use the following code.
#! /bin/sh
count=0
>out.txt
until [[ $n =~ 0 ]]; do
read -p 'Inputs: ' n
if [[ $n =~ ^[A-Z]$ ]]; then
count=`expr $count + 1`
echo $n >> out.txt
fi
done
echo The total number of valid input letters:
echo $count
echo " "
echo The first valid input:
sort out.txt |head -n 1
Output:
Inputs: B
Inputs: A
Inputs: C
Inputs: 0
The total number of valid input letters:
3
The first valid input:
A
Since you want only the smallest (in alphabet order) valid input, you don't need sort. Here's an alternative answer not using sort but just keep the smallest valid input:
#!/bin/sh
count=0
until [[ $n =~ 0 ]]; do
echo Inputs:
read n
if [[ $n =~ ^[A-Z]$ ]]; then
((count++))
if [ -z $first ] || [ `expr $n \< $first` -eq 1 ]; then
first=$n
fi
fi
done
echo The total number of valid input letters:
echo $count
echo " "
echo The first valid input:
echo $first
I would like to split a line into words. I know this can be done with this
For word in $line; do echo $word; done
But I want to make group of 3-3 words. So my question is, how can I split a line in group of 3-3 words ?
For example
Input : I am writing this line for testing the code.
Output :
I am writing
this line for
testing the code.
Read the words three at a time. Set the line being read from to the remainder:
while read -r remainder
do
while [[ -n $remainder ]]
do
read -r a b c remainder <<< "$remainder"
echo "$a $b $c"
done
done < inputfile
What about paste command
for word in $line; do echo $word; done | paste - - -
for word in $line; do echo $word; done | paste -d" " - - -
Easy regex exercise.
sed -e "s/\([^\ ]*\ [^\ ]*\ [^\ ]*\)\ /\1\\`echo -e '\n\r'`/g"
The only tricky part was getting the new line in the sed, as there isn't a standard for that.
$ echo "I am writing this line for testing the code."|sed -e "s/\([^\ ]*\ [^\ ]*\ [^\ ]*\)\ /\1\\`echo -e '\n\r'`/g"
I am writing
this line for
testing the code.
You're welcome.
Just use set to set your input as positional arguments, and process them in groups of three. That way you don't need anything fancy or bash-specific:
line="I am writing this line for testing the code."
set junk $line
shift
while [ $# -ge 3 ]; do
echo "Three words: $1 $2 $3"
shift 3
done
As a start you can use this, which reads every word into an array
#!/bin/bash
total=0
while read
do
for word in $REPLY
do
A[$total]=$word
total=$(($total+1))
done
done < input.txt
for i in "${A[#]}"
do
echo $i
done
Next step is to use seq or similar to loop through the array and print it in groups of three.
There's a non-generic straight forward solution:
#!/bin/bash
path_to_file=$1
while read line
do
counter=1;
for word in $line
do
echo -n $word" ";
if (($counter % 3 == 0))
then
echo "";
fi
let counter=counter+1;
done
done < ${path_to_file}
Save that in a script, give it a name (test.sh for example) and set it to execution mode. Than if your text is saved in "myfile.txt" call it like this:
test.sh myfile.txt
Here's an example of possible solution.
#!/bin/bash
line="I am writing this line for testing the code."
i=0
for word in $line; do
((++i))
if [[ $i -eq 3 ]]; then
i=0
echo "$word"
else
echo -ne "$word "
fi
done