Bash 변수의 새 줄

Bash 변수의 새 줄

Bash 변수에 여러 줄을 저장하려고 하는데 작동하지 않는 것 같습니다.

예를 들어, /bin한 줄에 파일을 나열하고 저장한 $LS다음 $LSstdin으로 전달하면 wc항상 1이 반환됩니다.

$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1

화면에 출력하려고 하면 다양한 결과가 나타납니다. echo모든 줄을 한 줄에 인쇄하지만 printf첫 번째 줄만 인쇄합니다.

#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS

그렇다면 bash 변수에 여러 줄이 포함될 수 있나요?

답변1

큰따옴표로 묶어야 합니다(그리고~해야 한다 큰따옴표 변수대부분의 경우에):

echo "$LS"

하지만에코를 사용하지 마십시오변수 내용을 인쇄하려면 다음을 사용하십시오.printf로 변경:

printf '%s\n' "$LS"

답변2

개행 문자가 변수에 있습니다. LS=$(ls -1)변수를 LS출력 ( 출력이 터미널로 가는 것을 제외하고는 ls -1동일한 출력을 생성함 )에서 후행 줄 바꿈을 뺀 출력으로 설정합니다.ls

문제는 개행 문자를 제거하려는 값을 인쇄할 때입니다. 쉘 스크립트에서는 $LS"변수의 값"을 의미하는 것이 아니라 LS"값을 가져와서 LS단어로 나누고 IFS각 단어를 글로브 패턴으로 해석합니다"를 의미합니다. 값을 얻으려면 LS를 쓰거나 "$LS"더 일반적으로는 $LS큰따옴표 안에 넣어야 합니다.

echo "$LS"LS백슬래시 문자를 해석하는 일부 쉘과 로 시작하는 몇 가지 값을 제외하고 인쇄된 값입니다 -.

printf "$LS"LS퍼센트 또는 백슬래시 문자를 포함하지 않고 (대부분의 구현에서) 로 시작하지 않는 한 인쇄할 값입니다 -.

값을 정확하게 인쇄하려면 LS를 사용하십시오 printf %s "$LS". 끝에 개행 문자를 추가하려면 를 사용하십시오 printf '%s\n' "$LS".

이는 일반적 으로 $(ls)현재 디렉터리에 있는 파일 목록이 아닙니다. 이것은 충분히 길들인 파일 이름이 있는 경우에만 작동합니다. 파일 이름 목록을 얻으려면(점 파일 제외) 와일드카드를 사용해야 합니다: *. 결과는 문자열이 아닌 문자열 목록이므로 문자열 변수에 할당할 수 없습니다. files=(*)이를 지원하는 셸(ksh93, bash, zsh)에서 배열 변수를 사용할 수 있습니다.

자세한 내용은 다음을 참조하세요.공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?

답변3

전에 언급한

printf '%s\n' "$LS"

유일한 올바른 해결책입니다.

제안된 다른 솔루션이echo그리고printf, 전혀 작동하지 않습니다.

$ mkdir t
$ cd t
$ touch \\n
$ LS=$(ls -l)
$ echo "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf "$LS\n"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf '%s\n' "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ ls -l
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ rm \\n
$ cd ..
$ rmdir t
$

V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"( 및 변형을 사용하여 테스트 할 수도 있습니다 .)

\n파일명이 흔하지 않을 수도 있지만 ,git diff변수로 변환하면 리터럴을 만날 가능성이 \n크게 늘어납니다.

관련 정보