Bash 변수에 여러 줄을 저장하려고 하는데 작동하지 않는 것 같습니다.
예를 들어, /bin
한 줄에 파일을 나열하고 저장한 $LS
다음 $LS
stdin으로 전달하면 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
크게 늘어납니다.