우아한 멀티라인 쉘 스트링

17862 단어 shellzshshowdevbash

Photo by Wendy van Zyl from Pexels




여러 줄 문자열의 상태



쉘의 여러 줄 문자열은 고통스럽습니다.

다음 내용이 포함된 쉘 스크립트를 사용하여 파일을 생성한다고 가정합니다.

export default class Greeter {
  greet(name: string) { return 'Hello, ' + name + '!'; }
}


어떻게 달성할 수 있습니까?

몇 가지 방법



방법 1: 여러 줄 변수



이 간단한 솔루션은 변수 정의가 들여쓰기되지 않은 경우에 작동합니다.

var="export default class Greeter {
  greet(name: string) { return 'Hello, ' + name + '!'; }
}"



$ echo $var
export default class Greeter {
  greet(name: string) { return 'Hello, ' + name + '!'; }
}


그러나 함수 내에서 $var를 정의하고 나머지 함수 본문과 함께 들여쓰기를 원하면 어떻게 될까요?

function my_function() {
  var="export default class Greeter {
    greet(name: string) { return 'Hello, ' + name + '!'; }
  }"
  echo $var
}



$ my_function
export default class Greeter {
    greet(name: string) { return 'Hello, ' + name + '!'; }
  }


아, 그건 분명히 우리가 원하는 것이 아닙니다.

따라서 간단한 변수 할당: 변수 정의가 들여쓰기되지 않은 매우 제한된 하위 집합에서 작동합니다. 다른 방법을 시도해 보겠습니다.

방법 2: 줄 바꿈을 위해 ' \n '이 있는 한 줄 변수



이 방법에서는 여러 줄 문자열의 모든 줄 바꿈을 \n 줄 바꿈 문자로 바꿉니다.

function my_function() {
  var="export default class Greeter {\n  greet(name: string) { return 'Hello, ' + name + '!'; }\n}"
  echo $var
}



$ my_function
export default class Greeter {
  greet(name: string) { return 'Hello, ' + name + '!'; }
}


결과는 좋아 보이지만 방법이 엉망입니다. 이것을 다음과 같이 다시 포맷하고 싶다면 어떻게 해야 할까요?

export default class Greeter {
  greet(name: string) {
    return 'Hello, ' + name + '!';
  }
}


여기에는 들여쓰기와 일치하도록 더 많은\n 문자와 공백을 추가해야 합니다. 매우 간단하지 않습니다.

function my_function() {
  var="export default class Greeter {\n  greet(name: string) {\n    return 'Hello, ' + name + '!';\n  }\n}"
  echo $var
}


따라서 명시적 줄 바꿈 문자: 서식을 지정하려는 텍스트가 자주 변경되지 않고 구현의 가독성이 중요하지 않은 경우 작동합니다. 텍스트 생성 코드 자체를 읽거나 유지 관리할 수 있기를 원한다면 이것은 좋은 솔루션이 아닙니다.

그래서 우리는 무엇을 더 할 수 있습니까?

방법 3: Heredocs



여러 줄 문자열은 다음을 위해 만들어졌습니다Heredocs:

In computing, a here document (here-document, here-text, heredoc, hereis, here-string or here-script) is a file literal or input stream literal: it is a section of a source code file that is treated as if it were a separate file. The term is also used for a form of multiline string literals that use similar syntax, preserving line breaks and other whitespace (including indentation) in the text.



그래서 그들이 우리의 문제에 대해 얼마나 잘 작동하는지 봅시다.

function my_function() {
  var=$(cat <<EOF
  export default class Greeter {
    greet(name: string) { return 'Hello, ' + name + '!'; }
  }
  EOF)
  echo $var
}



$ my_function
/Users/andrew/test.sh:8: parse error near `var=$(cat <<EOF'


오, 어, 예, 분명히 구분 기호 시퀀스(이 경우 EOF)는 들여쓰기가 불가능하고 한 줄에 단독으로 나타나야 하므로 다음과 같이 작성해야 합니다.

function my_function() {
  var=$(cat <<EOF
  export default class Greeter {
    greet(name: string) { return 'Hello, ' + name + '!'; }
  }
EOF
  )
  echo $var
}


...괜찮지만 함수 본문의 나머지 부분에 대한 들여쓰기를 깨뜨리는 것입니다. 또한 작동하지 않습니다.

$ my_function
  export default class Greeter {
    greet(name: string) { return 'Hello, ' + name + '!'; }
  }


방법 #1과 마찬가지로 이 방법은 우리가 원하지 않는 함수 본문을 들여쓰는 데 사용한 공백을 출력에 추가합니다.

그렇다면 어떻게 우리가 원하는 들여쓰기만을 보존할 수 있습니까?

나의 방법



내가하는 방법은 다음과 같습니다.

function my_function() {
  var="$(sed -e 's/^[ ]*\| //g' -e '1d;$d' <<'--------------------'
    | 
    | export default class Greeter {
    |   greet(name: string) { return `Hello, ${name}!`; }
    | }
    | 
--------------------
    )"
  echo $var
}


파이프 문자|를 사용하여 "여백"을 정의한 다음 sed 사용하여 제거합니다. sed -e 's/^[ ]*\| //g' 는 줄 시작 부분( [ ]* ), 파이프( ^ ), 공백 문자 하나( | )의 시작 부분에서 원하는 만큼의 공백 문자( [ ] )를 제거합니다.

This "margin" method was inspired by Scala's String#stripMargin functionality, which behaves in a very similar way.



두 번째 sed 표현식인 -e '1d;$d' 는 첫 번째 줄과 마지막 줄을 제거합니다. 변수에 쓰려는 내용 주위에 약간의 시각적 공백을 제공하기 위해 빈 줄을 추가합니다. 이 빈 줄 중 하나 또는 둘 다를 원하지 않으면 내 방법을 약간 변형하여 제거하십시오.

function my_function() {
  var="$(sed -e 's/^[ ]*\| //g' <<'--------------------'
    | export default class Greeter {
    |   greet(name: string) { return `Hello, ${name}!`; }
    | }
--------------------
    )"
  echo $var
}


하이픈 줄도 EOF 대체로 신경 쓰지 않습니다. 내용의 위쪽 및 아래쪽 여백과 같은 역할을 하기 때문입니다. 하지만, 내가 위에서와 같이 heredoc 구분 기호를 따옴표로 묶는 경우 공백을 포함할 수도 있습니다. 그래서 당신은 다음과 같은 것을 할 수 있습니다.

function my_function() {
  var="$(sed -e 's/^[ ]*\| //g' <<'    +'
    | export default class Greeter {
    |   greet(name: string) { return `Hello, ${name}!`; }
    | }
    +
    )"
  echo $var
}


나는 개인적으로 이것이 콘텐츠 아래에 너무 많은 공백을 남기고 있다고 생각합니다. 또한 많은 구문 강조 알고리즘이 이에 문제가 있습니다.

이러한 변형을 사용하여 원하는 수준으로 콘텐츠를 들여쓸 수 있습니다.

function my_function_1() {
  var="$(sed -e 's/^[ ]*\| //g' <<'--------------------'
    | export default class Greeter {
    |   greet(name: string) { return `Hello, ${name}!`; }
    | }
--------------------
    )"
  echo $var
}

function my_function_2() {
  var="$(sed -e 's/^[ ]*\| //g' <<'--------------------'
| export default class Greeter {
|   greet(name: string) { return `Hello, ${name}!`; }
| }
--------------------
    )"
  echo $var
}

function my_function_3() {
  var="$(sed -e 's/^[ ]*\| //g' <<'--------------------'
              | export default class Greeter {
              |   greet(name: string) { return `Hello, ${name}!`; }
              | }
--------------------
    )"
  echo $var
}



$ my_function_1; my_function_2; my_function_3
export default class Greeter {
  greet(name: string) { return `Hello, ${name}!`; }
}
export default class Greeter {
  greet(name: string) { return `Hello, ${name}!`; }
}
export default class Greeter {
  greet(name: string) { return `Hello, ${name}!`; }
}


시각적 미학과 결합된 이 방법의 유연성은 최근에 쉘에서 여러 줄 문자열을 사용하는 이유가 되었습니다.


awwsmm.com에서 내 글을 더 확인하십시오.

좋은 웹페이지 즐겨찾기