bash에서 문자열이 어떤 값으로 시작하는지 어떻게 확인할 수 있습니까?
문자열이 "node"(예 : "node001")로 시작하는지 확인하고 싶습니다. 같은 것
if [ $HOST == user* ]
then
echo yes
fi
어떻게하면 올바로 할 수 있습니까?
HOST가 "user1"인지 또는 "node"로 시작하는지 확인하기 위해 표현식을 결합해야합니다.
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
올바르게하는 방법?
Advanced Bash Scripting Guide 의이 스 니펫 은 다음과 같이 말합니다.
# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.
[[ $a == z* ]] # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
그래서 거의 정확했습니다. 단일 대괄호가 아니라 이중 대괄호가 필요했습니다 .
두 번째 질문과 관련하여 다음과 같이 작성할 수 있습니다.
HOST=user1
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes1
fi
HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes2
fi
에코가
yes1
yes2
Bash의 if
구문은 (IMO)에 익숙해지기 어렵습니다.
최근 bash (v3 +)를 사용하는 경우 bash 정규식 비교 연산자 =~
, 즉
if [[ "$HOST" =~ ^user.* ]]; then
echo "yes"
fi
this or that
정규식에서 일치하려면 |
, 즉
if [[ "$HOST" =~ ^user.*|^host1 ]]; then
echo "yes"
fi
주-이것은 '적절한'정규식 구문입니다.
user*
의 의미use
와 0 개 이상의 발생이r
있으므로use
및userrrr
일치합니다.user.*
수단user
및 모든 문자의 제로 또는-이상의 발생, 그래서user1
,userX
일치합니다.^user.*
user.*
$ HOST의 시작 부분에 있는 패턴과 일치 함을 의미합니다 .
정규 표현식 구문에 익숙하지 않은 경우이 리소스를 참조하세요 .
참고-각각의 새로운 질문을 새로운 질문으로 묻는 것이 더 낫습니다. 그러면 stackoverflow가 더 깔끔하고 유용 해집니다. 참조를 위해 언제든지 이전 질문으로 돌아가는 링크를 포함 할 수 있습니다.
스크립팅의 주요 포인트 중 하나가 이식성이기 때문에 항상 bash 확장을 사용하는 대신 POSIX sh를 고수하려고합니다. ( 프로그램 연결 외에도 대체하지 않음)
sh에서는 "is-prefix"조건을 확인하는 쉬운 방법이 있습니다.
case $HOST in node*)
your code here
esac
얼마나 오래된 감안할 때, 비전 및 crufty 쉬입니다 (배쉬는 치료되지 않습니다 : 그것은 더 적은 일관성이 적은 휴대용, 복잡), 나는 아주 좋은 기능적인 측면을 지적하고 싶습니다 일부 구문 요소는 좋아하지만 case
내장되어 있습니다 , 결과 구조는 다른 작업과 다르지 않습니다. 동일한 방식으로 구성 할 수 있습니다.
if case $HOST in node*) true;; *) false;; esac; then
your code here
fi
또는 더 짧게
if case $HOST in node*) ;; *) false;; esac; then
your code here
fi
또는 더 짧습니다 ( !
언어 요소로 표시하기 위해-하지만 지금은 나쁜 스타일입니다)
if ! case $HOST in node*) false;; esac; then
your code here
fi
명시 적이기를 좋아한다면 고유 한 언어 요소를 작성하십시오.
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
이것은 실제로 꽤 멋지지 않습니까?
if beginswith node "$HOST"; then
your code here
fi
그리고 sh는 기본적으로 작업과 문자열 목록 (및 내부적으로 작업이 구성되는 프로세스) 일 뿐이므로 이제 가벼운 함수 프로그래밍을 수행 할 수도 있습니다.
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }
all() {
test=$1; shift
for i in "$@"; do
$test "$i" || return
done
}
all "beginswith x" x xy xyz ; checkresult # prints TRUE
all "beginswith x" x xy abc ; checkresult # prints FALSE
이것은 우아합니다. 내가 sh를 사용하여 진지하게 옹호하는 것은 아닙니다. 실제 요구 사항에서 너무 빨리 깨집니다 (람다가 없어서 문자열을 사용해야합니다.하지만 문자열로 함수 호출을 중첩하는 것은 불가능하며 파이프는 불가능합니다 ...)
확인하려는 문자열 부분 만 선택할 수 있습니다.
if [ ${HOST:0:4} = user ]
후속 질문의 경우 OR를 사용할 수 있습니다 .
if [[ $HOST == user1 || $HOST == node* ]]
이미 게시 된 다른 방법을 선호하지만 일부 사람들은 다음을 사용하고 싶어합니다.
case "$HOST" in
user1|node*)
echo "yes";;
*)
echo "no";;
esac
편집하다:
위의 사례 진술에 귀하의 대안을 추가했습니다.
편집 한 버전에는 대괄호가 너무 많습니다. 다음과 같아야합니다.
if [[ $HOST == user1 || $HOST == node* ]];
여기에서 대부분의 답변이 매우 정확하지만 대부분은 불필요한 바 시즘을 포함합니다. POSIX 매개 변수 확장 은 필요한 모든 것을 제공합니다.
[ "${host#user}" != "${host}" ]
과
[ "${host#node}" != "${host}" ]
${var#expr}
일치하는 가장 작은 접두사를 expr
제거 ${var}
하고 반환합니다. 따라서 가 ( )로 시작 ${host}
하지 않으면 ( )는 .user
node
${host#user}
${host#node}
${host}
expr
fnmatch()
와일드 카드를 허용 하므로 ${host#node??}
친구들도 작동합니다.
# bash에서 의미가 있기 때문에 다음 솔루션을 얻었습니다.
또한 공백 등을 극복하기 위해 문자열을 ""로 묶는 것이 좋습니다.
A="#sdfs"
if [[ "$A" == "#"* ]];then
echo "skip comment line"
fi
@OP, 두 질문 모두 case / esac을 사용할 수 있습니다.
string="node001"
case "$string" in
node*) echo "found";;
* ) echo "no node";;
esac
두 번째 질문
case "$HOST" in
node*) echo "ok";;
user) echo "ok";;
esac
case "$HOST" in
node*|user) echo "ok";;
esac
또는 배쉬 4.0
case "$HOST" in
user) ;&
node*) echo "ok";;
esac
Mark Rushakoff의 최고 순위 답변에 구문 세부 사항을 조금 더 추가했습니다.
표현식
$HOST == node*
다음과 같이 쓸 수도 있습니다.
$HOST == "node"*
The effect is the same. Just make sure the wildcard is outside the quoted text. If the wildcard is inside the quotes it will be interpreted literally (i.e. not as a wildcard).
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
doesn't work, because all of [, [[ and test recognize the same nonrecursive grammar. see section CONDITIONAL EXPRESSIONS in your bash man page.
As an aside, the SUSv3 says
The KornShell-derived conditional command (double bracket [[]]) was removed from the shell command language description in an early proposal. Objections were raised that the real problem is misuse of the test command ([), and putting it into the shell is the wrong way to fix the problem. Instead, proper documentation and a new shell reserved word (!) are sufficient.
Tests that require multiple test operations can be done at the shell level using individual invocations of the test command and shell logicals, rather than using the error-prone -o flag of test.
you'd need to write it this way, but test doesn't support it:
if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi
test uses = for string equality, more importantly it doesn't support pattern matching.
case
/ esac
has good support for pattern matching:
case $HOST in
user1|node*) echo yes ;;
esac
it has the added benefit that it doesn't depend on bash, the syntax is portable. from the Single Unix Specification, The Shell Command Language:
case word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac
I tweaked @markrushakoff's answer to make it a callable function:
function yesNo {
# prompts user with $1, returns true if response starts with y or Y or is empty string
read -e -p "
$1 [Y/n] " YN
[[ "$YN" == y* || "$YN" == Y* || "$YN" == "" ]]
}
Use it like this:
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] Y
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] yes
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n]
true
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false
$ if yesNo "asfd"; then echo "true"; else echo "false"; fi
asfd [Y/n] ddddd
false
Here is a more complex version that provides for a specified default value:
function toLowerCase {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
function yesNo {
# $1: user prompt
# $2: default value (assumed to be Y if not specified)
# Prompts user with $1, using default value of $2, returns true if response starts with y or Y or is empty string
local DEFAULT=yes
if [ "$2" ]; then local DEFAULT="$( toLowerCase "$2" )"; fi
if [[ "$DEFAULT" == y* ]]; then
local PROMPT="[Y/n]"
else
local PROMPT="[y/N]"
fi
read -e -p "
$1 $PROMPT " YN
YN="$( toLowerCase "$YN" )"
{ [ "$YN" == "" ] && [[ "$PROMPT" = *Y* ]]; } || [[ "$YN" = y* ]]
}
Use it like this:
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N]
false
$ if yesNo "asfd" n; then echo "true"; else echo "false"; fi
asfd [y/N] y
true
$ if yesNo "asfd" y; then echo "true"; else echo "false"; fi
asfd [Y/n] n
false
grep
Forgetting performance, this is POSIX and looks nicer than case
solutions:
mystr="abcd"
if printf '%s' "$mystr" | grep -Eq '^ab'; then
echo matches
fi
Explanation:
printf '%s'
to preventprintf
from expanding backslash escapes: bash printf literal verbatim stringgrep -q
prevents echo of matches to stdout: How to check if a file contains a specific string using Bashgrep -E
enables extended regular expressions, which we need for the^
Another thing you can do is cat
out what you are echoing and pipe with inline cut -c 1-1
'Programing' 카테고리의 다른 글
라이브러리를 사용하지 않고 JavaScript에서 다른 요소 뒤에 요소를 삽입하는 방법은 무엇입니까? (0) | 2020.10.02 |
---|---|
Java를 사용하여 문자열을 텍스트 파일에 어떻게 저장합니까? (0) | 2020.10.02 |
DateTime 대 DateTimeOffset (0) | 2020.10.02 |
Java Vector (및 Stack) 클래스가 더 이상 사용되지 않거나 더 이상 사용되지 않는 것으로 간주되는 이유는 무엇입니까? (0) | 2020.10.02 |
R에서 "="와 "<-"할당 연산자의 차이점은 무엇입니까? (0) | 2020.10.02 |