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
Related
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
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.
My code looks something like this:
for line in `cat fileName`
do
if [[ $line == "Marker 1" ]]
then
while [[ $line != "---" ]]
do
#basically I want to read all the data below "Marker 1" till "---"
echo $line
((line++)) #this is wrong
done
elif [[ $line == "Marker 2" ]]
then
while [[ $line != "---" ]]
do
echo $line
((line++))
done
fi
done
How do I increment the value of $line when in the while loop? ((line++)) doesn't work
Using sed
If the goal is to echo all the lines from a line with Marker 1 or Marker 2 to a line with ---, then that entire shell loop can be replaced with this simple sed command:
sed -n '/^Marker [12]$/,/^---$/p' File
Example
Consider this test file:
$ cat File
beginning
Marker 1
one
---
more
Marker 2
two
Two
---
end
Now, let's run our command:
$ sed -n '/^Marker [12]$/,/^---$/p' File
Marker 1
one
---
Marker 2
two
Two
---
Using awk
With the same test file:
$ awk '/^Marker [12]$/,/^---$/' File
Marker 1
one
---
Marker 2
two
Two
---
((line++)) is for incrementing an integer value.
But the value of line in your example is a string.
In fact what you seem to want is get the next line from the file.
You need a different approach for that, and use while read instead of a for-loop.
#!/usr/bin/env bash
read_and_print_until_dashes() {
while read -r line; do
[[ $line = '---' ]] && break
echo "$line"
done
}
while read -r line; do
if [[ $line = "Marker 1" ]]; then
echo "$line"
read_and_print_until_dashes
elif [[ $line = "Marker 2" ]]; then
echo "$line"
read_and_print_until_dashes
fi
done < file.txt
I am doing something interesting with bash
I wrote script below:
#!/bin/bash
while :
do
if [ -s /tmp/file.txt ]; then
for line in $(cat /tmp/file.txt)
do
echo $line
#May be some commands here
done
fi
done
and the content of my file.txt is:
1 True
2 Flase
How can I say the script if command cat /tmp/file.txt is finished (I mean all lines are read) and also echo $line and other commands are finished then break the infinitive while : loop?
Thank you
Use break.
#!/bin/bash
while :
do
if [ -s /tmp/file.txt ]; then
for line in $(cat /tmp/file.txt)
do
echo $line
#May be some commands here
done
break
fi
done
Although it would be simpler and more proper with:
#!/bin/bash
for (( ;; )); do
if [[ -s /tmp/file.txt ]]; then
# Never use `for X in $()` when reading output/input. Using word splitting
# method for it could be a bad idea in many ways. One is it's dependent with
# IFS. Second is that glob patterns like '*' could be expanded and you'd
# produce filenames instead.
while read line; do
# Place variables between quotes or else it would be subject to Word
# Splitting and unexpected output format could be made.
echo "$line"
done < /tmp/file.txt
break
fi
done
On another note, do you really need the outer loop? This time you don't need to use break.
#!/bin/bash
if [[ -s /tmp/file.txt ]]; then
while read line; do
echo "$line"
done < /tmp/file.txt
fi
I have a shell script like this:
cat file | while read line
do
# run some commands using $line
done
Now I need to check if the line contains any non-whitespace character ([\n\t ]), and if not, skip it.
How can I do this?
Since read reads whitespace-delimited fields by default, a line containing only whitespace should result in the empty string being assigned to the variable, so you should be able to skip empty lines with just:
[ -z "$line" ] && continue
try this
while read line;
do
if [ "$line" != "" ]; then
# Do something here
fi
done < $SOURCE_FILE
bash:
if [[ ! $line =~ [^[:space:]] ]] ; then
continue
fi
And use done < file instead of cat file | while, unless you know why you'd use the latter.
cat i useless in this case if you are using while read loop. I am not sure if you meant you want to skip lines that is empty or if you want to skip lines that also contain at least a white space.
i=0
while read -r line
do
((i++)) # or $(echo $i+1|bc) with sh
case "$line" in
"") echo "blank line at line: $i ";;
*" "*) echo "line with blanks at $i";;
*[[:blank:]]*) echo "line with blanks at $i";;
esac
done <"file"
if ! grep -q '[^[:space:]]' ; then
continue
fi
blank=`tail -1 <file-location>`
if [ -z "$blank" ]
then
echo "end of the line is the blank line"
else
echo "their is something in last line"
fi
awk 'NF' file | while read line
do
# run some commands using $line
done
stole this answer to a similar question:
Delete empty lines using sed