while-loop and if-statement do different command if condition is met
Clash Royale CLAN TAG#URR8PPP
up vote
2
down vote
favorite
Inside file.txt
chicken sheep cow
tomato cucumber
banana
Without if
statement
while read -r column1 column2 column3; do
command
done < file.txt
Using if
statement, how to if the line has three columns, it do command1
, if it has two columns, do command2
and if only has one column, it do command3
?
bash shell-script text-processing
add a comment |Â
up vote
2
down vote
favorite
Inside file.txt
chicken sheep cow
tomato cucumber
banana
Without if
statement
while read -r column1 column2 column3; do
command
done < file.txt
Using if
statement, how to if the line has three columns, it do command1
, if it has two columns, do command2
and if only has one column, it do command3
?
bash shell-script text-processing
(What if there are more than three? Thatread
would concatenate the fourth and so on with the third one.)
â ilkkachu
Oct 29 '17 at 22:50
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Inside file.txt
chicken sheep cow
tomato cucumber
banana
Without if
statement
while read -r column1 column2 column3; do
command
done < file.txt
Using if
statement, how to if the line has three columns, it do command1
, if it has two columns, do command2
and if only has one column, it do command3
?
bash shell-script text-processing
Inside file.txt
chicken sheep cow
tomato cucumber
banana
Without if
statement
while read -r column1 column2 column3; do
command
done < file.txt
Using if
statement, how to if the line has three columns, it do command1
, if it has two columns, do command2
and if only has one column, it do command3
?
bash shell-script text-processing
edited Oct 29 '17 at 19:40
asked Oct 29 '17 at 19:21
Hidayats
3017
3017
(What if there are more than three? Thatread
would concatenate the fourth and so on with the third one.)
â ilkkachu
Oct 29 '17 at 22:50
add a comment |Â
(What if there are more than three? Thatread
would concatenate the fourth and so on with the third one.)
â ilkkachu
Oct 29 '17 at 22:50
(What if there are more than three? That
read
would concatenate the fourth and so on with the third one.)â ilkkachu
Oct 29 '17 at 22:50
(What if there are more than three? That
read
would concatenate the fourth and so on with the third one.)â ilkkachu
Oct 29 '17 at 22:50
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
3
down vote
accepted
Or other approach with smallest difference of your example:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt
Output will be:
All three columns has data
Only first and second columns has data
Only first column has data
Notes:
In your example first and second lines contains several spaces at the end, but by default read
removes all leading and trailing space characters.
If your input contains more than 3 columns, all data in third column and further will placed in column3
See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
You need to quote the variables in the tests:[ -n "$var" ]
etc. With-z
it works without the quotes here, slightly accidentally, since if$var
is empty in[ -z $var ]
, the expansion is just[ -z ]
which just tests if-z
is a nonempty string. The one with-n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
add a comment |Â
up vote
1
down vote
You may read each line into array with read -ra
, then, check the array size:
fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt
Of course, expression printf "$fmt" $#items[*] $items[-1]
was used just for demonstration, you can define your own.
The above approach outputs(as an example):
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
add a comment |Â
up vote
1
down vote
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
or
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
add a comment |Â
up vote
0
down vote
Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash
or ksh
( which also can be handy in case we do want to keep positional parameters). The below example is for bash
( note that for ksh
or mksh
you'd use -A
insead of -a
in read
, and of course change #!
line):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "$#arr[@]" in
1) printf "One column in line %dn" "$line_counter";;
2) printf "Two columns in line %dn" "$line_counter";;
3) printf "Three columns in line %dn" "$line_counter";;
*) printf "More than 3 lines in line %dn" "$line_counter";;
esac
((line_counter++))
done < input.txt
And the output is like so:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Or other approach with smallest difference of your example:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt
Output will be:
All three columns has data
Only first and second columns has data
Only first column has data
Notes:
In your example first and second lines contains several spaces at the end, but by default read
removes all leading and trailing space characters.
If your input contains more than 3 columns, all data in third column and further will placed in column3
See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
You need to quote the variables in the tests:[ -n "$var" ]
etc. With-z
it works without the quotes here, slightly accidentally, since if$var
is empty in[ -z $var ]
, the expansion is just[ -z ]
which just tests if-z
is a nonempty string. The one with-n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
add a comment |Â
up vote
3
down vote
accepted
Or other approach with smallest difference of your example:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt
Output will be:
All three columns has data
Only first and second columns has data
Only first column has data
Notes:
In your example first and second lines contains several spaces at the end, but by default read
removes all leading and trailing space characters.
If your input contains more than 3 columns, all data in third column and further will placed in column3
See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
You need to quote the variables in the tests:[ -n "$var" ]
etc. With-z
it works without the quotes here, slightly accidentally, since if$var
is empty in[ -z $var ]
, the expansion is just[ -z ]
which just tests if-z
is a nonempty string. The one with-n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Or other approach with smallest difference of your example:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt
Output will be:
All three columns has data
Only first and second columns has data
Only first column has data
Notes:
In your example first and second lines contains several spaces at the end, but by default read
removes all leading and trailing space characters.
If your input contains more than 3 columns, all data in third column and further will placed in column3
See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
Or other approach with smallest difference of your example:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt
Output will be:
All three columns has data
Only first and second columns has data
Only first column has data
Notes:
In your example first and second lines contains several spaces at the end, but by default read
removes all leading and trailing space characters.
If your input contains more than 3 columns, all data in third column and further will placed in column3
See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
edited Oct 30 '17 at 5:19
answered Oct 29 '17 at 20:00
Egor Vasilyev
1,792129
1,792129
You need to quote the variables in the tests:[ -n "$var" ]
etc. With-z
it works without the quotes here, slightly accidentally, since if$var
is empty in[ -z $var ]
, the expansion is just[ -z ]
which just tests if-z
is a nonempty string. The one with-n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
add a comment |Â
You need to quote the variables in the tests:[ -n "$var" ]
etc. With-z
it works without the quotes here, slightly accidentally, since if$var
is empty in[ -z $var ]
, the expansion is just[ -z ]
which just tests if-z
is a nonempty string. The one with-n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
You need to quote the variables in the tests:
[ -n "$var" ]
etc. With -z
it works without the quotes here, slightly accidentally, since if $var
is empty in [ -z $var ]
, the expansion is just [ -z ]
which just tests if -z
is a nonempty string. The one with -n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)â ilkkachu
Oct 29 '17 at 22:48
You need to quote the variables in the tests:
[ -n "$var" ]
etc. With -z
it works without the quotes here, slightly accidentally, since if $var
is empty in [ -z $var ]
, the expansion is just [ -z ]
which just tests if -z
is a nonempty string. The one with -n
, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)â ilkkachu
Oct 29 '17 at 22:48
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
@ilkkachu, thx. It's fair remark, answer was changed
â Egor Vasilyev
Oct 30 '17 at 5:22
add a comment |Â
up vote
1
down vote
You may read each line into array with read -ra
, then, check the array size:
fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt
Of course, expression printf "$fmt" $#items[*] $items[-1]
was used just for demonstration, you can define your own.
The above approach outputs(as an example):
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
add a comment |Â
up vote
1
down vote
You may read each line into array with read -ra
, then, check the array size:
fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt
Of course, expression printf "$fmt" $#items[*] $items[-1]
was used just for demonstration, you can define your own.
The above approach outputs(as an example):
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You may read each line into array with read -ra
, then, check the array size:
fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt
Of course, expression printf "$fmt" $#items[*] $items[-1]
was used just for demonstration, you can define your own.
The above approach outputs(as an example):
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
You may read each line into array with read -ra
, then, check the array size:
fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt
Of course, expression printf "$fmt" $#items[*] $items[-1]
was used just for demonstration, you can define your own.
The above approach outputs(as an example):
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
edited Oct 29 '17 at 19:46
answered Oct 29 '17 at 19:32
RomanPerekhrest
22.5k12145
22.5k12145
add a comment |Â
add a comment |Â
up vote
1
down vote
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
or
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
add a comment |Â
up vote
1
down vote
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
or
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
add a comment |Â
up vote
1
down vote
up vote
1
down vote
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
or
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
or
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
answered Oct 29 '17 at 19:58
Hauke Laging
53.6k1282130
53.6k1282130
add a comment |Â
add a comment |Â
up vote
0
down vote
Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash
or ksh
( which also can be handy in case we do want to keep positional parameters). The below example is for bash
( note that for ksh
or mksh
you'd use -A
insead of -a
in read
, and of course change #!
line):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "$#arr[@]" in
1) printf "One column in line %dn" "$line_counter";;
2) printf "Two columns in line %dn" "$line_counter";;
3) printf "Three columns in line %dn" "$line_counter";;
*) printf "More than 3 lines in line %dn" "$line_counter";;
esac
((line_counter++))
done < input.txt
And the output is like so:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3
add a comment |Â
up vote
0
down vote
Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash
or ksh
( which also can be handy in case we do want to keep positional parameters). The below example is for bash
( note that for ksh
or mksh
you'd use -A
insead of -a
in read
, and of course change #!
line):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "$#arr[@]" in
1) printf "One column in line %dn" "$line_counter";;
2) printf "Two columns in line %dn" "$line_counter";;
3) printf "Three columns in line %dn" "$line_counter";;
*) printf "More than 3 lines in line %dn" "$line_counter";;
esac
((line_counter++))
done < input.txt
And the output is like so:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash
or ksh
( which also can be handy in case we do want to keep positional parameters). The below example is for bash
( note that for ksh
or mksh
you'd use -A
insead of -a
in read
, and of course change #!
line):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "$#arr[@]" in
1) printf "One column in line %dn" "$line_counter";;
2) printf "Two columns in line %dn" "$line_counter";;
3) printf "Three columns in line %dn" "$line_counter";;
*) printf "More than 3 lines in line %dn" "$line_counter";;
esac
((line_counter++))
done < input.txt
And the output is like so:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3
Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash
or ksh
( which also can be handy in case we do want to keep positional parameters). The below example is for bash
( note that for ksh
or mksh
you'd use -A
insead of -a
in read
, and of course change #!
line):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "$#arr[@]" in
1) printf "One column in line %dn" "$line_counter";;
2) printf "Two columns in line %dn" "$line_counter";;
3) printf "Three columns in line %dn" "$line_counter";;
*) printf "More than 3 lines in line %dn" "$line_counter";;
esac
((line_counter++))
done < input.txt
And the output is like so:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3
answered Oct 30 '17 at 6:03
Sergiy Kolodyazhnyy
7,85811548
7,85811548
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f401270%2fwhile-loop-and-if-statement-do-different-command-if-condition-is-met%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
(What if there are more than three? That
read
would concatenate the fourth and so on with the third one.)â ilkkachu
Oct 29 '17 at 22:50