Check if a shell variable has more than one line using built-ins?
up vote
3
down vote
favorite
I can do this by calling the external utility sed
(for a known non-empty $myvar
) like so:
if [ "$(printf %s "$myvar" | sed -n '$=')" -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Is there a way to do this using only bash
builtins?
Even better, is there a way to do this in a POSIX-specified manner, without calling external utilities?
(This question is one of curiosity and finding better ways to do things; the above code does function. I'm wondering if there is a cleaner/faster way.)
bash shell-script string posix
add a comment |
up vote
3
down vote
favorite
I can do this by calling the external utility sed
(for a known non-empty $myvar
) like so:
if [ "$(printf %s "$myvar" | sed -n '$=')" -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Is there a way to do this using only bash
builtins?
Even better, is there a way to do this in a POSIX-specified manner, without calling external utilities?
(This question is one of curiosity and finding better ways to do things; the above code does function. I'm wondering if there is a cleaner/faster way.)
bash shell-script string posix
1
With that function, the result ofmyvar="ab"
is exactly the same as the result ofmyvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.
– user79743
Apr 19 '16 at 23:07
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
1
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what ifmyvar=''
orunset myvar
?
– user79743
Apr 19 '16 at 23:38
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; theecho
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.
– Wildcard
Apr 19 '16 at 23:45
1
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19
add a comment |
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I can do this by calling the external utility sed
(for a known non-empty $myvar
) like so:
if [ "$(printf %s "$myvar" | sed -n '$=')" -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Is there a way to do this using only bash
builtins?
Even better, is there a way to do this in a POSIX-specified manner, without calling external utilities?
(This question is one of curiosity and finding better ways to do things; the above code does function. I'm wondering if there is a cleaner/faster way.)
bash shell-script string posix
I can do this by calling the external utility sed
(for a known non-empty $myvar
) like so:
if [ "$(printf %s "$myvar" | sed -n '$=')" -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Is there a way to do this using only bash
builtins?
Even better, is there a way to do this in a POSIX-specified manner, without calling external utilities?
(This question is one of curiosity and finding better ways to do things; the above code does function. I'm wondering if there is a cleaner/faster way.)
bash shell-script string posix
bash shell-script string posix
edited Apr 20 '16 at 2:14
user79743
asked Apr 16 '16 at 3:38
Wildcard
22.5k959164
22.5k959164
1
With that function, the result ofmyvar="ab"
is exactly the same as the result ofmyvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.
– user79743
Apr 19 '16 at 23:07
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
1
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what ifmyvar=''
orunset myvar
?
– user79743
Apr 19 '16 at 23:38
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; theecho
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.
– Wildcard
Apr 19 '16 at 23:45
1
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19
add a comment |
1
With that function, the result ofmyvar="ab"
is exactly the same as the result ofmyvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.
– user79743
Apr 19 '16 at 23:07
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
1
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what ifmyvar=''
orunset myvar
?
– user79743
Apr 19 '16 at 23:38
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; theecho
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.
– Wildcard
Apr 19 '16 at 23:45
1
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19
1
1
With that function, the result of
myvar="ab"
is exactly the same as the result of myvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.– user79743
Apr 19 '16 at 23:07
With that function, the result of
myvar="ab"
is exactly the same as the result of myvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.– user79743
Apr 19 '16 at 23:07
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
1
1
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what if
myvar=''
or unset myvar
?– user79743
Apr 19 '16 at 23:38
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what if
myvar=''
or unset myvar
?– user79743
Apr 19 '16 at 23:38
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; the
echo
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.– Wildcard
Apr 19 '16 at 23:45
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; the
echo
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.– Wildcard
Apr 19 '16 at 23:45
1
1
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19
add a comment |
5 Answers
5
active
oldest
votes
up vote
10
down vote
accepted
The POSIX way:
NL='
'
case $myvar in
*"$NL"*) echo more than one line ;;
*) echo one line ;;
esac
This also works in pre-POSIX Bourne-like shells, too.
add a comment |
up vote
5
down vote
The following snippets works in bash
(with and without the -posix
option):
#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'n'* ]]; }
version_2 () {
local newlines="${myvar//[^$'n']/}"
[[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
if $test; then echo many lines; else echo one line; fi
done
add a comment |
up vote
4
down vote
There are several options (bash first, POSIX is below).
The code inside each function could be easily used outside.
#!/bin/bash
nl=$'n'
aregex (){ [[ $a =~ $nl ]]; }
apattern (){ [[ $a == *$nl* ]]; }
acut (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs ()( IFS="$nl"
set -f; set -- x${a}x;
(( $# > 1 ));
)
aread (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
(( "${#b[@]}" > 1 )); }
Each function is an option. Each function will exit with a return value of 0 if there is only one line and a return value of 1 if the variable $a
has more than one new-line (more than one $'n'
).
After a function is executed, this will print the line required:
out=''; "$function" && out="more than "
printf "%9s = %sone linen" "$1" "$out"
Executing all options:
a='ab'"$nl"'cd' ; alltests
a='ab cd' ; alltests
Gives this output:
aregex = more than one line
apattern = more than one line
acut = more than one line
areplace = more than one line
acase = more than one line
aifs = more than one line
aread = more than one line
aregex = one line
apattern = one line
acut = one line
areplace = one line
acase = one line
aifs = one line
aread = one line
POSIX
The following options fail in POSIX for several reasons:
- aregex : There is no regex
=~
operators in POSIX. - apattern : There is no
==
operator in POSIX. - areplace : Parameter expansion does not have the
${ / / }
option.
Four could safely be translated to POSIX:
- posixcut : Probably the best solution.
- posixcase : A common solution for POSIX shells.
- posixifs : Executed inside a sub-shell to be able to set
set -f
. - posixread : read does not have
-d
or-a
but it could be adapted.
#!/bin/dash
nl='
'
posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
posixread(){ local b=0;
while IFS=$nl read -r _; do
b=$((b+1));
[ $b -gt 1 ] && break;
done <<-_EOT_
x${a}x
_EOT_
[ $b -gt 1 ];
}
Note: Yes, local
is not strictly POSIX, but is pretty well supported.
The local for b
, could be safely removed (check for global $b
usage).
Bourne (1977 shell).
If you need code for the original 1977 Bourne shell, use this:
posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
bourneread()( b=0 ### A helper function.
while :; do
if IFS=$nl read c && [ $b -le 1 ]; then
b=`expr $b + 1`
else
echo "$b"
break
fi
done <<-_EOT_
x${a}x
_EOT_
)
posixread (){ [ `bourneread` -gt 1 ]; }
The expansion ${a%% }
used in posixcut will not work in Bourne.
The posixifs needs to be divided in two parts to work in Bourne.
The read option needs mayor changes, but works correctly.
Its function is posixread, the bourneread is a required helper function.
All code for Bourne was tested to be working correctly with heirloom shell.
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't supportset --
either. It may have supportedset - $var
, butset -
alone would still be the same asset
(again from vague memory). There, you'd needset x $var; shift
.
– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks likeset -
worked there. The need forset x $var; shift
might have been for another shell. Note thatyash
at least doesn't supportset - $var
.
– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yesset x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.
– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
|
show 1 more comment
up vote
1
down vote
Here is a way that should work with all Bourne syntax / POSIX shells and uses only builtins :
if (set -f ; IFS=$'n'; set -- x${myvar}x ; [ $# = 1 ]) ; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have exactly one line"
fi
If your shell doesn't support IFS=$'n'
(like dash
0.5.7), you can use instead :
IFS="
"
I think this you need to setIFS
otherwise the answer is wrong:sh -c 'a="x y"; set -- $a; echo $#'
prints2
for me,sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints1
.
– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
Theset -f
will apply to future commands. You needset -f
; set -- $myvar. Also
set -- $myvar` on amyvar=$'nnxnnn'
would split into 1 element. Andmyvar=''
ormyvar=$'nnn'
into 0.
– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used twoset
instructions when tolf I was missing-f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.
– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
|
show 5 more comments
up vote
1
down vote
I'd recommend using Bash parameter expansion as follows:
n="${myvar//[^n]}"; if [ ${#n} -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Test Samples:
myvar="xxx"
myvar="xxnxx"
myvar="xxnxnx"
add a comment |
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
accepted
The POSIX way:
NL='
'
case $myvar in
*"$NL"*) echo more than one line ;;
*) echo one line ;;
esac
This also works in pre-POSIX Bourne-like shells, too.
add a comment |
up vote
10
down vote
accepted
The POSIX way:
NL='
'
case $myvar in
*"$NL"*) echo more than one line ;;
*) echo one line ;;
esac
This also works in pre-POSIX Bourne-like shells, too.
add a comment |
up vote
10
down vote
accepted
up vote
10
down vote
accepted
The POSIX way:
NL='
'
case $myvar in
*"$NL"*) echo more than one line ;;
*) echo one line ;;
esac
This also works in pre-POSIX Bourne-like shells, too.
The POSIX way:
NL='
'
case $myvar in
*"$NL"*) echo more than one line ;;
*) echo one line ;;
esac
This also works in pre-POSIX Bourne-like shells, too.
edited Apr 18 '16 at 9:22
Stéphane Chazelas
296k54559902
296k54559902
answered Apr 16 '16 at 3:45
cuonglm
101k23197299
101k23197299
add a comment |
add a comment |
up vote
5
down vote
The following snippets works in bash
(with and without the -posix
option):
#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'n'* ]]; }
version_2 () {
local newlines="${myvar//[^$'n']/}"
[[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
if $test; then echo many lines; else echo one line; fi
done
add a comment |
up vote
5
down vote
The following snippets works in bash
(with and without the -posix
option):
#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'n'* ]]; }
version_2 () {
local newlines="${myvar//[^$'n']/}"
[[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
if $test; then echo many lines; else echo one line; fi
done
add a comment |
up vote
5
down vote
up vote
5
down vote
The following snippets works in bash
(with and without the -posix
option):
#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'n'* ]]; }
version_2 () {
local newlines="${myvar//[^$'n']/}"
[[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
if $test; then echo many lines; else echo one line; fi
done
The following snippets works in bash
(with and without the -posix
option):
#!/bin/bash
#!/bin/bash -posix
version_1 () { [[ "$myvar" = *$'n'* ]]; }
version_2 () {
local newlines="${myvar//[^$'n']/}"
[[ "${#newlines}" -eq 1 ]]
}
for test in version_1 version_2; do
if $test; then echo many lines; else echo one line; fi
done
edited Apr 16 '16 at 16:15
Gilles
523k12610441576
523k12610441576
answered Apr 16 '16 at 10:03
Lucas
1,988717
1,988717
add a comment |
add a comment |
up vote
4
down vote
There are several options (bash first, POSIX is below).
The code inside each function could be easily used outside.
#!/bin/bash
nl=$'n'
aregex (){ [[ $a =~ $nl ]]; }
apattern (){ [[ $a == *$nl* ]]; }
acut (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs ()( IFS="$nl"
set -f; set -- x${a}x;
(( $# > 1 ));
)
aread (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
(( "${#b[@]}" > 1 )); }
Each function is an option. Each function will exit with a return value of 0 if there is only one line and a return value of 1 if the variable $a
has more than one new-line (more than one $'n'
).
After a function is executed, this will print the line required:
out=''; "$function" && out="more than "
printf "%9s = %sone linen" "$1" "$out"
Executing all options:
a='ab'"$nl"'cd' ; alltests
a='ab cd' ; alltests
Gives this output:
aregex = more than one line
apattern = more than one line
acut = more than one line
areplace = more than one line
acase = more than one line
aifs = more than one line
aread = more than one line
aregex = one line
apattern = one line
acut = one line
areplace = one line
acase = one line
aifs = one line
aread = one line
POSIX
The following options fail in POSIX for several reasons:
- aregex : There is no regex
=~
operators in POSIX. - apattern : There is no
==
operator in POSIX. - areplace : Parameter expansion does not have the
${ / / }
option.
Four could safely be translated to POSIX:
- posixcut : Probably the best solution.
- posixcase : A common solution for POSIX shells.
- posixifs : Executed inside a sub-shell to be able to set
set -f
. - posixread : read does not have
-d
or-a
but it could be adapted.
#!/bin/dash
nl='
'
posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
posixread(){ local b=0;
while IFS=$nl read -r _; do
b=$((b+1));
[ $b -gt 1 ] && break;
done <<-_EOT_
x${a}x
_EOT_
[ $b -gt 1 ];
}
Note: Yes, local
is not strictly POSIX, but is pretty well supported.
The local for b
, could be safely removed (check for global $b
usage).
Bourne (1977 shell).
If you need code for the original 1977 Bourne shell, use this:
posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
bourneread()( b=0 ### A helper function.
while :; do
if IFS=$nl read c && [ $b -le 1 ]; then
b=`expr $b + 1`
else
echo "$b"
break
fi
done <<-_EOT_
x${a}x
_EOT_
)
posixread (){ [ `bourneread` -gt 1 ]; }
The expansion ${a%% }
used in posixcut will not work in Bourne.
The posixifs needs to be divided in two parts to work in Bourne.
The read option needs mayor changes, but works correctly.
Its function is posixread, the bourneread is a required helper function.
All code for Bourne was tested to be working correctly with heirloom shell.
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't supportset --
either. It may have supportedset - $var
, butset -
alone would still be the same asset
(again from vague memory). There, you'd needset x $var; shift
.
– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks likeset -
worked there. The need forset x $var; shift
might have been for another shell. Note thatyash
at least doesn't supportset - $var
.
– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yesset x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.
– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
|
show 1 more comment
up vote
4
down vote
There are several options (bash first, POSIX is below).
The code inside each function could be easily used outside.
#!/bin/bash
nl=$'n'
aregex (){ [[ $a =~ $nl ]]; }
apattern (){ [[ $a == *$nl* ]]; }
acut (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs ()( IFS="$nl"
set -f; set -- x${a}x;
(( $# > 1 ));
)
aread (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
(( "${#b[@]}" > 1 )); }
Each function is an option. Each function will exit with a return value of 0 if there is only one line and a return value of 1 if the variable $a
has more than one new-line (more than one $'n'
).
After a function is executed, this will print the line required:
out=''; "$function" && out="more than "
printf "%9s = %sone linen" "$1" "$out"
Executing all options:
a='ab'"$nl"'cd' ; alltests
a='ab cd' ; alltests
Gives this output:
aregex = more than one line
apattern = more than one line
acut = more than one line
areplace = more than one line
acase = more than one line
aifs = more than one line
aread = more than one line
aregex = one line
apattern = one line
acut = one line
areplace = one line
acase = one line
aifs = one line
aread = one line
POSIX
The following options fail in POSIX for several reasons:
- aregex : There is no regex
=~
operators in POSIX. - apattern : There is no
==
operator in POSIX. - areplace : Parameter expansion does not have the
${ / / }
option.
Four could safely be translated to POSIX:
- posixcut : Probably the best solution.
- posixcase : A common solution for POSIX shells.
- posixifs : Executed inside a sub-shell to be able to set
set -f
. - posixread : read does not have
-d
or-a
but it could be adapted.
#!/bin/dash
nl='
'
posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
posixread(){ local b=0;
while IFS=$nl read -r _; do
b=$((b+1));
[ $b -gt 1 ] && break;
done <<-_EOT_
x${a}x
_EOT_
[ $b -gt 1 ];
}
Note: Yes, local
is not strictly POSIX, but is pretty well supported.
The local for b
, could be safely removed (check for global $b
usage).
Bourne (1977 shell).
If you need code for the original 1977 Bourne shell, use this:
posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
bourneread()( b=0 ### A helper function.
while :; do
if IFS=$nl read c && [ $b -le 1 ]; then
b=`expr $b + 1`
else
echo "$b"
break
fi
done <<-_EOT_
x${a}x
_EOT_
)
posixread (){ [ `bourneread` -gt 1 ]; }
The expansion ${a%% }
used in posixcut will not work in Bourne.
The posixifs needs to be divided in two parts to work in Bourne.
The read option needs mayor changes, but works correctly.
Its function is posixread, the bourneread is a required helper function.
All code for Bourne was tested to be working correctly with heirloom shell.
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't supportset --
either. It may have supportedset - $var
, butset -
alone would still be the same asset
(again from vague memory). There, you'd needset x $var; shift
.
– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks likeset -
worked there. The need forset x $var; shift
might have been for another shell. Note thatyash
at least doesn't supportset - $var
.
– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yesset x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.
– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
|
show 1 more comment
up vote
4
down vote
up vote
4
down vote
There are several options (bash first, POSIX is below).
The code inside each function could be easily used outside.
#!/bin/bash
nl=$'n'
aregex (){ [[ $a =~ $nl ]]; }
apattern (){ [[ $a == *$nl* ]]; }
acut (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs ()( IFS="$nl"
set -f; set -- x${a}x;
(( $# > 1 ));
)
aread (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
(( "${#b[@]}" > 1 )); }
Each function is an option. Each function will exit with a return value of 0 if there is only one line and a return value of 1 if the variable $a
has more than one new-line (more than one $'n'
).
After a function is executed, this will print the line required:
out=''; "$function" && out="more than "
printf "%9s = %sone linen" "$1" "$out"
Executing all options:
a='ab'"$nl"'cd' ; alltests
a='ab cd' ; alltests
Gives this output:
aregex = more than one line
apattern = more than one line
acut = more than one line
areplace = more than one line
acase = more than one line
aifs = more than one line
aread = more than one line
aregex = one line
apattern = one line
acut = one line
areplace = one line
acase = one line
aifs = one line
aread = one line
POSIX
The following options fail in POSIX for several reasons:
- aregex : There is no regex
=~
operators in POSIX. - apattern : There is no
==
operator in POSIX. - areplace : Parameter expansion does not have the
${ / / }
option.
Four could safely be translated to POSIX:
- posixcut : Probably the best solution.
- posixcase : A common solution for POSIX shells.
- posixifs : Executed inside a sub-shell to be able to set
set -f
. - posixread : read does not have
-d
or-a
but it could be adapted.
#!/bin/dash
nl='
'
posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
posixread(){ local b=0;
while IFS=$nl read -r _; do
b=$((b+1));
[ $b -gt 1 ] && break;
done <<-_EOT_
x${a}x
_EOT_
[ $b -gt 1 ];
}
Note: Yes, local
is not strictly POSIX, but is pretty well supported.
The local for b
, could be safely removed (check for global $b
usage).
Bourne (1977 shell).
If you need code for the original 1977 Bourne shell, use this:
posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
bourneread()( b=0 ### A helper function.
while :; do
if IFS=$nl read c && [ $b -le 1 ]; then
b=`expr $b + 1`
else
echo "$b"
break
fi
done <<-_EOT_
x${a}x
_EOT_
)
posixread (){ [ `bourneread` -gt 1 ]; }
The expansion ${a%% }
used in posixcut will not work in Bourne.
The posixifs needs to be divided in two parts to work in Bourne.
The read option needs mayor changes, but works correctly.
Its function is posixread, the bourneread is a required helper function.
All code for Bourne was tested to be working correctly with heirloom shell.
There are several options (bash first, POSIX is below).
The code inside each function could be easily used outside.
#!/bin/bash
nl=$'n'
aregex (){ [[ $a =~ $nl ]]; }
apattern (){ [[ $a == *$nl* ]]; }
acut (){ [[ $a != "${a%%"$nl"*}" ]]; }
areplace (){ [[ $a != "${a//"$nl"/}" ]]; }
acase (){ case $a in (*$nl*) true;; (*) false;; esac; }
aifs ()( IFS="$nl"
set -f; set -- x${a}x;
(( $# > 1 ));
)
aread (){ IFS="$nl" read -rd '' -a b <<<"x${a}x";
(( "${#b[@]}" > 1 )); }
Each function is an option. Each function will exit with a return value of 0 if there is only one line and a return value of 1 if the variable $a
has more than one new-line (more than one $'n'
).
After a function is executed, this will print the line required:
out=''; "$function" && out="more than "
printf "%9s = %sone linen" "$1" "$out"
Executing all options:
a='ab'"$nl"'cd' ; alltests
a='ab cd' ; alltests
Gives this output:
aregex = more than one line
apattern = more than one line
acut = more than one line
areplace = more than one line
acase = more than one line
aifs = more than one line
aread = more than one line
aregex = one line
apattern = one line
acut = one line
areplace = one line
acase = one line
aifs = one line
aread = one line
POSIX
The following options fail in POSIX for several reasons:
- aregex : There is no regex
=~
operators in POSIX. - apattern : There is no
==
operator in POSIX. - areplace : Parameter expansion does not have the
${ / / }
option.
Four could safely be translated to POSIX:
- posixcut : Probably the best solution.
- posixcase : A common solution for POSIX shells.
- posixifs : Executed inside a sub-shell to be able to set
set -f
. - posixread : read does not have
-d
or-a
but it could be adapted.
#!/bin/dash
nl='
'
posixcut (){ [ "${a}" != "${a%%"$nl"*}" ] ; }
posixcase(){ case $a in (*$nl*) true;; (*) false;; esac; }
posixifs ()( IFS="$nl";
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
posixread(){ local b=0;
while IFS=$nl read -r _; do
b=$((b+1));
[ $b -gt 1 ] && break;
done <<-_EOT_
x${a}x
_EOT_
[ $b -gt 1 ];
}
Note: Yes, local
is not strictly POSIX, but is pretty well supported.
The local for b
, could be safely removed (check for global $b
usage).
Bourne (1977 shell).
If you need code for the original 1977 Bourne shell, use this:
posixcase() { case $a in *$nl*) true;; *) false;; esac; }
posixifs () ( IFS="$nl"
set -f; set -- x${a}x;
[ "$#" -gt 1 ];
)
bourneread()( b=0 ### A helper function.
while :; do
if IFS=$nl read c && [ $b -le 1 ]; then
b=`expr $b + 1`
else
echo "$b"
break
fi
done <<-_EOT_
x${a}x
_EOT_
)
posixread (){ [ `bourneread` -gt 1 ]; }
The expansion ${a%% }
used in posixcut will not work in Bourne.
The posixifs needs to be divided in two parts to work in Bourne.
The read option needs mayor changes, but works correctly.
Its function is posixread, the bourneread is a required helper function.
All code for Bourne was tested to be working correctly with heirloom shell.
edited Apr 19 '16 at 1:35
answered Apr 17 '16 at 8:11
user79743
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't supportset --
either. It may have supportedset - $var
, butset -
alone would still be the same asset
(again from vague memory). There, you'd needset x $var; shift
.
– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks likeset -
worked there. The need forset x $var; shift
might have been for another shell. Note thatyash
at least doesn't supportset - $var
.
– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yesset x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.
– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
|
show 1 more comment
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't supportset --
either. It may have supportedset - $var
, butset -
alone would still be the same asset
(again from vague memory). There, you'd needset x $var; shift
.
– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks likeset -
worked there. The need forset x $var; shift
might have been for another shell. Note thatyash
at least doesn't supportset - $var
.
– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yesset x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.
– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
The 1977 Bourne shell had no functions. I'd expect those kind of redirections wouldn't work great there either. Redirection was quite buggy back then there. It's a bit pointless trying to be portable to such an old shell anyway.
– Stéphane Chazelas
Apr 19 '16 at 10:02
IIRC, It didn't support
set --
either. It may have supported set - $var
, but set -
alone would still be the same as set
(again from vague memory). There, you'd need set x $var; shift
.– Stéphane Chazelas
Apr 19 '16 at 10:09
IIRC, It didn't support
set --
either. It may have supported set - $var
, but set -
alone would still be the same as set
(again from vague memory). There, you'd need set x $var; shift
.– Stéphane Chazelas
Apr 19 '16 at 10:09
Testing on a PDP11 emulator running Unix v7, it looks like
set -
worked there. The need for set x $var; shift
might have been for another shell. Note that yash
at least doesn't support set - $var
.– Stéphane Chazelas
Apr 19 '16 at 10:19
Testing on a PDP11 emulator running Unix v7, it looks like
set -
worked there. The need for set x $var; shift
might have been for another shell. Note that yash
at least doesn't support set - $var
.– Stéphane Chazelas
Apr 19 '16 at 10:19
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,
set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yes set x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas I fully agre with your words: ` It's a bit pointless trying to be portable to such an old shell anyway.` .... Yes,
set --
was not there originally: set -- was not implemented originally, but came with the second release of the Bourne shell.. ... ... Yes set x $var; shift
would be the usual workaround. ... ... ... ... Thanks for all your informative comments. Bye.– user79743
Apr 19 '16 at 10:32
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
@StéphaneChazelas Where is Unix v7 (for pdp11) available?
– user79743
Apr 19 '16 at 10:38
|
show 1 more comment
up vote
1
down vote
Here is a way that should work with all Bourne syntax / POSIX shells and uses only builtins :
if (set -f ; IFS=$'n'; set -- x${myvar}x ; [ $# = 1 ]) ; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have exactly one line"
fi
If your shell doesn't support IFS=$'n'
(like dash
0.5.7), you can use instead :
IFS="
"
I think this you need to setIFS
otherwise the answer is wrong:sh -c 'a="x y"; set -- $a; echo $#'
prints2
for me,sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints1
.
– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
Theset -f
will apply to future commands. You needset -f
; set -- $myvar. Also
set -- $myvar` on amyvar=$'nnxnnn'
would split into 1 element. Andmyvar=''
ormyvar=$'nnn'
into 0.
– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used twoset
instructions when tolf I was missing-f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.
– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
|
show 5 more comments
up vote
1
down vote
Here is a way that should work with all Bourne syntax / POSIX shells and uses only builtins :
if (set -f ; IFS=$'n'; set -- x${myvar}x ; [ $# = 1 ]) ; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have exactly one line"
fi
If your shell doesn't support IFS=$'n'
(like dash
0.5.7), you can use instead :
IFS="
"
I think this you need to setIFS
otherwise the answer is wrong:sh -c 'a="x y"; set -- $a; echo $#'
prints2
for me,sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints1
.
– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
Theset -f
will apply to future commands. You needset -f
; set -- $myvar. Also
set -- $myvar` on amyvar=$'nnxnnn'
would split into 1 element. Andmyvar=''
ormyvar=$'nnn'
into 0.
– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used twoset
instructions when tolf I was missing-f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.
– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
|
show 5 more comments
up vote
1
down vote
up vote
1
down vote
Here is a way that should work with all Bourne syntax / POSIX shells and uses only builtins :
if (set -f ; IFS=$'n'; set -- x${myvar}x ; [ $# = 1 ]) ; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have exactly one line"
fi
If your shell doesn't support IFS=$'n'
(like dash
0.5.7), you can use instead :
IFS="
"
Here is a way that should work with all Bourne syntax / POSIX shells and uses only builtins :
if (set -f ; IFS=$'n'; set -- x${myvar}x ; [ $# = 1 ]) ; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have exactly one line"
fi
If your shell doesn't support IFS=$'n'
(like dash
0.5.7), you can use instead :
IFS="
"
edited Apr 19 '16 at 10:04
user79743
answered Apr 17 '16 at 8:40
jlliagre
46.1k783132
46.1k783132
I think this you need to setIFS
otherwise the answer is wrong:sh -c 'a="x y"; set -- $a; echo $#'
prints2
for me,sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints1
.
– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
Theset -f
will apply to future commands. You needset -f
; set -- $myvar. Also
set -- $myvar` on amyvar=$'nnxnnn'
would split into 1 element. Andmyvar=''
ormyvar=$'nnn'
into 0.
– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used twoset
instructions when tolf I was missing-f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.
– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
|
show 5 more comments
I think this you need to setIFS
otherwise the answer is wrong:sh -c 'a="x y"; set -- $a; echo $#'
prints2
for me,sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints1
.
– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
Theset -f
will apply to future commands. You needset -f
; set -- $myvar. Also
set -- $myvar` on amyvar=$'nnxnnn'
would split into 1 element. Andmyvar=''
ormyvar=$'nnn'
into 0.
– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used twoset
instructions when tolf I was missing-f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.
– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
I think this you need to set
IFS
otherwise the answer is wrong: sh -c 'a="x y"; set -- $a; echo $#'
prints 2
for me, sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints 1
.– Lucas
Apr 17 '16 at 9:14
I think this you need to set
IFS
otherwise the answer is wrong: sh -c 'a="x y"; set -- $a; echo $#'
prints 2
for me, sh -c $'a="x y"; IFS="n"; set -- $a; echo $#'
on the other hand prints 1
.– Lucas
Apr 17 '16 at 9:14
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
@Lucas Thanks for your comment, answer updated.
– jlliagre
Apr 17 '16 at 10:11
The
set -f
will apply to future commands. You need set -f
; set -- $myvar. Also
set -- $myvar` on a myvar=$'nnxnnn'
would split into 1 element. And myvar=''
or myvar=$'nnn'
into 0.– Stéphane Chazelas
Apr 18 '16 at 9:30
The
set -f
will apply to future commands. You need set -f
; set -- $myvar. Also
set -- $myvar` on a myvar=$'nnxnnn'
would split into 1 element. And myvar=''
or myvar=$'nnn'
into 0.– Stéphane Chazelas
Apr 18 '16 at 9:30
@StéphaneChazelas Thanks Stéphane, I originally used two
set
instructions when tolf I was missing -f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.– jlliagre
Apr 18 '16 at 13:31
@StéphaneChazelas Thanks Stéphane, I originally used two
set
instructions when tolf I was missing -f
but overlook the issue introduced by an edit that came later. I agree empty lines are still an issue with this approach.– jlliagre
Apr 18 '16 at 13:31
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
@BinaryZebra no problem, the issue was tricky to detect.
– jlliagre
Apr 19 '16 at 6:42
|
show 5 more comments
up vote
1
down vote
I'd recommend using Bash parameter expansion as follows:
n="${myvar//[^n]}"; if [ ${#n} -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Test Samples:
myvar="xxx"
myvar="xxnxx"
myvar="xxnxnx"
add a comment |
up vote
1
down vote
I'd recommend using Bash parameter expansion as follows:
n="${myvar//[^n]}"; if [ ${#n} -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Test Samples:
myvar="xxx"
myvar="xxnxx"
myvar="xxnxnx"
add a comment |
up vote
1
down vote
up vote
1
down vote
I'd recommend using Bash parameter expansion as follows:
n="${myvar//[^n]}"; if [ ${#n} -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Test Samples:
myvar="xxx"
myvar="xxnxx"
myvar="xxnxnx"
I'd recommend using Bash parameter expansion as follows:
n="${myvar//[^n]}"; if [ ${#n} -eq 1 ]; then
echo "Your variable has only one line, proceeding"
else
echo "Error condition, variable must have only one line"
fi
Test Samples:
myvar="xxx"
myvar="xxnxx"
myvar="xxnxnx"
answered Nov 29 at 18:11
l3x
1213
1213
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f276834%2fcheck-if-a-shell-variable-has-more-than-one-line-using-built-ins%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
With that function, the result of
myvar="ab"
is exactly the same as the result ofmyvar=$'abn'
. Should a trailing newline be ignored?. In my opinion, it shouldn't.– user79743
Apr 19 '16 at 23:07
@BinaryZebra, you are absolutely correct for the general case. In my specific case, I was setting the variable in the first place using command substitution, so was guaranteed to have no trailing newlines.
– Wildcard
Apr 19 '16 at 23:10
1
So, if the variable has no trailing "new line" and contains no "new line" it should be counted as "one line". If a trailing "new line" is added, it should be counted as "one more", correct?. There is only one case left that the function with sed fails to process and in my opinion should be counted as "one line" (there are no "new lines" included in the variable). ... ... ... what if
myvar=''
orunset myvar
?– user79743
Apr 19 '16 at 23:38
@BinaryZebra, this is what I get for failing to assiduously reduce my code to a simplest case standalone example. :) The conditional line itself is taken from my actual production script; the
echo
lines are obviously filler. Earlier in the script (just after the command substitution) I checked that the variable started with the expected pattern—so I already know the variable is not empty or unset. This is my question post, not an answer, so I don't feel it's necessary to edit it at this point, but feel free to propose one if you see a simple way to make it clearer.– Wildcard
Apr 19 '16 at 23:45
1
Yes, You need a "simplest case standalone example". :-) ... No edit needed, it is already becoming "an old question", but I took the liberty of proposing one :-) ... feel free to simply "reverse the edit" if you don't like it for any reason. I hope this is the end of the history for this question. Bye.
– user79743
Apr 20 '16 at 2:19