태그 보관물: variable

variable

들여 쓰기하는 동안 여러 줄의 변수에 문자열 값을 할당하는 방법은 무엇입니까? 할 수 있습니다. VAR=”This displays without \ any issues.” echo

문제:

  1. 변수에 꽤 긴 값을 할당해야합니다.
  2. 내 스크립트의 모든 줄은 특정 수의 열 아래에 있어야합니다.

그래서 둘 이상의 줄을 사용하여 할당하려고합니다.

들여 쓰기없이 간단하게 수행 할 수 있습니다.

VAR="This displays without \
any issues."
echo "${VAR}"

결과:

This displays without any issues.

그러나 들여 쓰기가있는 경우 :

    VAR="This displays with \
    extra spaces."
    echo "${VAR}"

결과:

This displays with      extra spaces.

이 공백없이 어떻게 우아하게 할당 할 수 있습니까?



답변

여기서 문제는 변수를 큰 따옴표 ( “”)로 묶는 것입니다. 제거하면 문제가 해결됩니다.

    VAR="This displays with \
    extra spaces."
    echo ${VAR}

산출

 This displays with extra spaces.

여기서 문제는 변수를 큰 따옴표로 묶으면 모든 공백 문자가 유지된다는 것입니다. 명시 적으로 필요한 경우에 사용할 수 있습니다.

예를 들어

$ echo "Hello     World    ........ ...            ...."

인쇄합니다

Hello     World    ........ ...            ....

따옴표를 제거하면 다른

$ echo Hello     World    ........ ...            ....
Hello World ........ ... ....

여기서 Bash는 첫 번째 경우 전체 텍스트가 “단일”인수로 간주되어 추가 공백을 유지하므로 텍스트에서 여분의 공백을 제거합니다. 그러나 두 번째 경우 echo명령은 텍스트를 5 개의 인수로받습니다.

인수를 명령에 전달할 때 변수를 인용하는 것도 도움이됩니다.

아래 명령에서 echo단일 인수 만 가져 옵니다."Hello World"

$ variable="Hello World"
$ echo "$variable"

하지만 아래의 시나리오의 경우 echo로 두 개의 인수를 얻을 수 HelloWorld

$ variable="Hello World"
$ echo $variable

답변

esuoxuMickaël Bucas 가 제공하는 솔루션 은이 작업을 수행하는 일반적이고 이식 가능한 방법입니다.

다음은 몇 가지 bash솔루션입니다 (일부 솔루션은 다른 쉘에서도 작동해야 함 zsh). 먼저 +=append 연산자를 사용하십시오 (정수 변수, 일반 변수 및 배열 각각에 대해 약간 다른 방식으로 작동 함).

text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
text+="tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
text+="quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ..."

텍스트에 줄 바꿈 (또는 다른 공백 / 이스케이프)을 원하면 $''따옴표를 대신 사용하십시오.

text=$'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n'
text+=$'...'

다음 printf -v으로 형식화 된 값을 변수에 할당하는 데 사용

printf -v text "%s" "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed " \
                    "do eiusmod empor incididunt ut labore et dolore magna aliqua. "\
                    "Ut enim ad minim veniam ..."

여기서 속임수는 형식 지정자보다 많은 인수가 있으므로 대부분의 printf함수 와 달리 bash는 형식 문자열이 끝날 때까지 서식 문자열을 재사용합니다. \n형식 문자열 내에 를 넣거나 $ ”(또는 둘 다)를 사용하여 공백을 처리 할 수 ​​있습니다.

다음으로 배열을 사용하십시오.

text=("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
      "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
      "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ..." )

+=텍스트를 한 줄씩 작성하는 데 사용할 수도 있습니다 (참고 ()).

text+=("post script")

그러나 전체 텍스트 내용을 한 번에 원한다면 배열을 “평평하게”기억해야합니다.

echo "$text"      # only outputs index [0], the first line
echo "${text[*]}" # output complete text (joined by first character of IFS)

(정수 인덱스 배열은 연관 배열과 달리 암시 적으로 정렬됩니다.) 이렇게하면 선을 조작하고 필요한 경우 슬라이스 및 주사위를 만들 수 있기 때문에 약간의 유연성이 제공 됩니다.

마지막으로 reador readarray및 “here-document”를 사용하십시오.

read -r -d '' text <<-"EOT"
        Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea ...
EOT

readarray -t textarray <<-"EOT"
        Lorem [...]
EOT

여기서 문서 형식은 <<-모든 주요 하드 탭이 입력에서 제거됨 을 의미하므로 텍스트를 들여 쓰려면 탭을 사용해야합니다. 인용 "EOT"부호는 쉘 확장 기능을 방지하므로 입력이 그대로 사용됩니다. 로 read그것을 읽을 수 있도록 그것은, NUL 바이트로 구분 된 입력을 사용하는 줄 바꿈은 한 번에 텍스트를 구분. 로 readarray(일명 mapfile가능한 사람 떠들썩한 파티-4.0)이 배열로 판독하고, -t각 행 바꿈 스트립.


답변

모든 줄의 시작 부분에 을 제거하는 특별한 heredoc 구문이 있습니다 : “<<-“(대시 추가됨)

http://tldp.org/LDP/abs/html/here-docs.html

예 19-4. 탭이 억제 된 여러 줄 메시지

다음과 같이 사용할 수 있습니다.

v="$(cat <<-EOF
    A
        B
    C
EOF
)"
echo "$v"

결과 :

A
B
C

공백이 아닌 탭에서만 작동합니다.


답변

쉘이 원하지 않는 줄 바꿈과 다음 공간을 먹도록하십시오.

$ cat weird.sh
#!/bin/sh

        var1="A weird(?) $(
             )multi line $(
             )text idea. $(
             )PID=$$"

        var2='You can '$(
            )'avoid expansion '$(
            )'too: PID=$$'

        var3='Or mix it: '$(
            )'To insert the PID use $$. '$(
            )"It expands to e.g. $$."

        echo "$var1"
        echo "$var2"
        echo "$var3"
$ sh weird.sh
A weird(?) multi line text idea. PID=13960
You can avoid expansion too: PID=$$
Or mix it: To insert the PID use $$. It expands to e.g. 13960.

따라서 가능하지만 …이 솔루션을 좋아하거나 싫어하는 것은 맛의 문제입니다 …


답변

아마도 당신은 이것을 시도 할 수 있습니다.

          echo "Test" \
               "Test2" \
               "Test3"

답변

이것은 내가 당신이 그것을해야한다고 제안하는 방법이며, 그 이유를 설명 할 것이지만, 먼저 다른 것에 대해 이야기하고 싶습니다 …

set -- 'Arg 1: Line 1.' \
       'Arg 2: Line 2.' \
       'and so on for'  \
       'as long as you might like.'
var="$*"

여기에있는 다른 많은 해결책은 확장 방법을 변경하여 쉘 변수의 내용에 어떻게 든 영향을 줄 수 있다고 제안하는 것 같습니다. 나는 이것이 사실이 아니라고 확신 할 수있다.

    string="some stuff here \
            some more stuff here."
    echo $string ${#string}
    echo "$string" "${#string}"

산출

some stuff here some more stuff here. 53
some stuff here                 some more stuff here. 53

위에서 본 것은 먼저 필드 분할 확장, 확장 소스 변수의 바이트 수에 대한 보고서, 따옴표로 구분 된 확장 및 동일한 바이트 수입니다. 출력은 다를 수 있지만 쉘 변수의 내용은 $string할당을 제외하고 전혀 변경되지 않습니다.

더군다나, 왜 그런지 이해하지 못한다면, 조만간 매우 불쾌한 놀라움에 직면하게 될 것입니다. 다시 시도하지만 약간 다른 조건에서 시도하겠습니다.

    IFS=sf
    echo $string ${#string}
    echo "$string" "${#string}"

동일 $string-다른 환경.

산출

 ome  tu   here                  ome more  tu   here. 53
some stuff here                 some more stuff here. 53

필드 분할은에 정의 된 필드 구분 기호를 기반으로합니다 $IFS. $IFS공백과 $IFS다른 두 가지 구분 기호가 있습니다. 기본적으로 3 개의 가능한 공백 값인 $IFS공간 탭 줄 바꾸기 가 지정 $IFS됩니다. 위에서 볼 수 있듯이 쉽게 변경되며 필드 분할 확장에 큰 영향을 줄 수 있습니다.

$IFS공백은 순서대로 단일 필드로 echo제거되므로 공백을 $IFS포함 할 때 공백 시퀀스를 포함하는 확장 은 단일 공백으로 만 평가됩니다 echo. 공백에 대한 인수를 연결 하기 때문 입니다. 그러나 어떤 공백이 아닌 값은 같은 방식으로 생략하다하지 않으며, 각각의 발생 구분 기호는 항상 자신에게 필드를 얻을 수 -에서 볼 수있는 물건 위의 확장.

이것은 최악이 아닙니다. 이 다른 것을 고려하십시오 $string.

IFS=$space$tab$newline
cd emptydir
    string=" * * * \
             * * * "
    echo $string ${#string}
    echo "$string" "${#string}"

산출

* * * * * * 30
 * * *                  * * *  30

알 겠어? 자, 환경을 다시 바꿔 봅시다.

    touch file1 file2 file3 file4 file5
    echo $string ${#string}
    echo "$string" "${#string}"

산출

file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
 * * *                  * * *  30

우와

기본적으로 쉘은 파일 이름이 일치 할 경우 파일 이름 글로브를 확장합니다. 이는 매개 변수 확장 및 구문 분석 순서에서 필드 분할 후에 발생 하므로 인용되지 않은 문자열은 이러한 방식으로 취약합니다. 원하는 경우이 동작을 해제 할 수 set -f있지만 POSIX 호환 쉘은 항상 기본적으로 사용됩니다.

이것은 들여 쓰기 환경 설정에 맞게 확장에 따옴표를 놓을 때 대비하는 종류입니다. 그럼에도 불구하고 모든 경우에 확장 동작에 관계없이 실제 값 $string은 항상 마지막으로 할당했을 때의 값입니다 . 첫 번째로 돌아 갑시다.

set -- 'Arg 1: Line 1.' \
       'Arg 2: Line 2.' \
       'and so on for'  \
       'as long as you might like.'
var="$*"
echo "$var" "${#var}"

산출

Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70

나는 이것이 쉘 구문을 들여 쓰기 환경 설정에 적용하는 훨씬 더 안전한 방법이라고 생각합니다. 위에서하고있는 것은 각 개별 문자열을 위치 매개 변수에 할당하는 것입니다. 위치 매개 변수는 각각 $1또는 유사한 번호로 참조 할 수 있습니다. ${33}그런 다음 $var특수 쉘 매개 변수 를 사용하여 연결된 값을 할당합니다 $*.

이 접근법은에도 면역이되지 않습니다 $IFS. 그럼에도 불구하고, 나는 이와 관련 $IFS하여 추가 혜택 과의 관계를 고려합니다 . 치다:

IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"

echo "$space_split"
echo "$slash_split"
echo "$new_line_split"

산출

Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.

보다시피 , 첫 번째 바이트에서 $*각 arg를 연결합니다 . 따라서 다르게 할당 된 상태에서 값을 저장하면 저장된 각 값마다 다른 필드 구분 기호가 사용됩니다. 위에서 본 것은 각 변수의 리터럴 값입니다. 구분자를 전혀 원하지 않으면 다음을 수행하십시오."$@"$IFS$IFS

IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"

산출

Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67

답변

시도해 볼 수 있습니다 :

echo $VAR | tr -s " "

또는

myArr=($VAL)
VAL=${myArr[@]}
echo "$VAL"

또한 당신은 확인할 수 있습니다 밖으로.