[string] Bash 변수에서 공백을 자르는 방법?

이 코드가있는 쉘 스크립트가 있습니다.

var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

그러나 항상 hg st하나 이상의 줄 바꾸기 문자를 인쇄 하기 때문에 조건부 코드는 항상 실행 됩니다.

  • 에서 공백을 제거하는 간단한 방법이 있나요 $var(같은 trim()에서 PHP는 )?

또는

  • 이 문제를 처리하는 표준 방법이 있습니까?

sed 또는 AWK 사용할 수는 있지만이 문제에 대한보다 우아한 해결책이 있다고 생각합니다.



답변

선행, 후행 및 중간 공백이 포함 된 변수를 정의 해 보겠습니다.

FOO=' test test test '
echo -e "FOO='${FOO}'"
# > FOO=' test test test '
echo -e "length(FOO)==${#FOO}"
# > length(FOO)==16

어떻게 (로 표시 모든 공백을 제거하는 방법 [:space:]에를 tr)

FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
# > FOO_NO_WHITESPACE='testtesttest'
echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
# > length(FOO_NO_WHITESPACE)==12

선행 공백 만 제거하는 방법 :

FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
# > FOO_NO_LEAD_SPACE='test test test '
echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
# > length(FOO_NO_LEAD_SPACE)==15

후행 공백 만 제거하는 방법 :

FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
# > FOO_NO_TRAIL_SPACE=' test test test'
echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
# > length(FOO_NO_TRAIL_SPACE)==15

선행 및 후행 공백을 제거하는 방법-체인을 연결하십시오 sed.

FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
# > FOO_NO_EXTERNAL_SPACE='test test test'
echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
# > length(FOO_NO_EXTERNAL_SPACE)==14

배시가 지원하는 경우 또는, 당신은 대체 할 수 echo -e "${FOO}" | sed ...sed ... <<<${FOO}과 같이 (공백을 후행) :

FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"


답변

간단한 대답은 다음과 같습니다.

echo "   lol  " | xargs

Xargs 가 트리밍을 수행합니다. 매개 변수가없는 하나의 명령 / 프로그램이므로 손질 된 문자열을 쉽게 반환합니다!

참고 : 이렇게하면 모든 내부 공간이 제거되지 않으므로 "foo bar"그대로 유지됩니다. 되지 않습니다 "foobar". 그러나, 여러 공간이 하나의 공간으로 응축 될 것이다, 그렇게 "foo bar"될 것입니다 "foo bar". 또한 줄 끝 문자를 제거하지 않습니다.


답변

와일드 카드 라는 Bash 내장 기능 만 사용하는 솔루션이 있습니다 .

var="    abc    "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"   
printf '%s' "===$var==="

다음은 함수에 같은 내용이 포함되어 있습니다.

trim() {
    local var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"   
    printf '%s' "$var"
}

따옴표로 묶은 문자열을 전달합니다. 예 :

trim "   abc   "

이 솔루션의 좋은 점은 POSIX 호환 쉘에서 작동한다는 것입니다.

참고


답변

Bash에는 매개 변수 확장 이라는 기능이 있는데, 그 중에서도 소위 패턴을 기반으로 문자열을 대체 할 수 있습니다 (패턴은 정규식과 유사하지만 근본적인 차이점과 한계가 있습니다). [flussence의 원래 줄 : Bash에는 정규 표현식이 있지만 잘 숨겨져 있습니다.]

다음 은 변수 값에서 공백을 모두 제거하는 방법을 보여줍니다 .

$ var='abc def'
$ echo "$var"
abc def
# Note: flussence's original expression was "${var/ /}", which only replaced the *first* space char., wherever it appeared.
$ echo -n "${var//[[:space:]]/}"
abcdef


답변

문자열의 시작과 끝에서 모든 공백을 제거하려면 (줄 끝 문자 포함) :

echo $variable | xargs echo -n

중복 된 공간도 제거됩니다 :

echo "  this string has a lot       of spaces " | xargs echo -n

생성 : ‘이 문자열에는 많은 공간이 있습니다’


답변

하나의 선행 및 후행 공간 제거

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

예를 들면 다음과 같습니다.

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

산출:

'one leading', 'one trailing', 'one leading and one trailing'

스트립 모든 선행 및 후행 공백을

trim()
{
    local trimmed="$1"

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

예를 들면 다음과 같습니다.

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

산출:

'two leading', 'two trailing', 'two leading and two trailing'


답변

장갑판의 배쉬 가이드 섹션에서

매개 변수 확장에서 extglob을 사용하려면

 #Turn on extended globbing  
shopt -s extglob
 #Trim leading and trailing whitespace from a variable  
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}  
 #Turn off extended globbing  
shopt -u extglob  

함수에 래핑 된 동일한 기능은 다음과 같습니다 (참고 : 함수에 전달 된 입력 문자열을 인용해야 함).

trim() {
    # Determine if 'extglob' is currently on.
    local extglobWasOff=1
    shopt extglob >/dev/null && extglobWasOff=0
    (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
    # Trim leading and trailing whitespace
    local var=$1
    var=${var##+([[:space:]])}
    var=${var%%+([[:space:]])}
    (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
    echo -n "$var"  # Output trimmed string.
}

용법:

string="   abc def ghi  ";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim "$string");
echo "$trimmed";

서브 쉘에서 실행되도록 함수를 변경하면 extglob에 대한 현재 쉘 옵션을 검사하는 것에 대해 걱정할 필요가 없으며, 현재 쉘에 영향을주지 않고 설정할 수 있습니다. 이것은 기능을 엄청나게 단순화시킵니다. 또한 위치 매개 변수를 “제자리에”업데이트하므로 로컬 변수가 필요하지 않습니다.

trim() {
    shopt -s extglob
    set -- "${1##+([[:space:]])}"
    printf "%s" "${1%%+([[:space:]])}"
}

그래서:

$ s=$'\t\n \r\tfoo  '
$ shopt -u extglob
$ shopt extglob
extglob         off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo  '<
>foo<
$ shopt extglob
extglob         off