파일에서 읽은 다음 for를 사용하여 필드를 분할하지만 따옴표는 유지합니다.

파일에서 읽은 다음 for를 사용하여 필드를 분할하지만 따옴표는 유지합니다.

이것이 내가 bash 쉘 스크립트에서 얻으려고 하는 것입니다:

for a in "1" "2 3" "4 5 6"
do
  echo "a: $a"
done
a: 1
a: 2 3
a: 4 5 6

그러나 변수를 사용하면 따옴표가 다르게 처리됩니다.

echo "\"1\" \"2 3\" \"4 5 6\"" > a.txt

cat a.txt
"1" "2 3" "4 5 6"

read aline < a.txt

변수를 큰따옴표로 인용하면 다음과 같은 결과가 나타납니다.

for b in "$aline"
do
  echo "b: $b"
done
b: "1" "2 3" "4 5 6"

따옴표가 없으면 다음과 같은 결과를 얻습니다.

for b in $aline
do
  echo "b: $b"
done
b: "1"
b: "2
b: 3"
b: "4
b: 5
b: 6"

첫 번째 예와 같이 변수의 내용을 처리할 수 있는 방법이 있습니까?

답변1

견적 처리 외에 전체 패키지(변수/산술/명령 확장, 와일드카드 등)를 사용하는 데 동의하는 경우 다음을 수행할 수 있습니다.

echo '"a b" "x         y"' >a.txt

eval "set -- $(<a.txt)"
for b do
    printf 'b: %s\n' "$b"
done

b: a b
b: x         y

(또는 또는 같은 다른 고급 쉘)이 아닌 일반 쉘에서 작동하도록 하려면 $(<a.txt)로 변경하십시오. 무엇을 제어할 수 있는지 확신하는 경우에만 이 옵션을 사용하십시오. 그렇지 않으면 분할, 명령 확장 등을 통해 스크립트를 활용하는 것이 쉽지 않습니다.$(cat a.txt)bashzshksha.txt;

그러나 이러한 매개변수를 명령에 전달하려는 경우 xargs확장 없이 따옴표만 처리하는 를 사용할 수 있습니다.

xargs <a.txt printf 'b: %s\n'

그러나 xargs이는 쉘 함수가 아닌 외부 명령에만 작동하며 큰따옴표 안의 백슬래시는 작은따옴표 안의 백슬래시처럼 무시되며 여러 줄 문자열은 구문 분석할 수 없습니다.

후자의 제한이 문제가 되지 않으면 xargs래퍼나 배열을 통해 인용 구문 분석기로 사용할 수 있습니다.

mapfile -t args < <(xargs <a.txt printf '%s\n')
for b in "${args[@]}"; do
        printf 'b: %s\n' "$b"
done

답변2

bash그렇지 않은 경우 ksh93( ksh93쉘이 bash어쨌든 모방하려고 시도함) 내장 옵션을 사용하여 csv를 읽을 수 있습니다 -S( read그래서 csv 스타일 인용을 이해합니다).

IFS=" " read -rSA array < a.txt
printf 'a: %s\n' "${array[@]}"

이를 사용하면 변수의 내용을 코드인 것처럼 표시하는 매개변수 확장 플래그 (참조는 이해되지만 코드는 평가되지 않음 )와 매개변수 확장 플래그를 zsh사용 하여 1레벨 참조를 제거할 수 있습니다.zzshzshevalQ

IFS= read -r line < a.txt
printf 'a: %s\n' "${(Q@)${(z)line}}"

( @매개변수 확장 플래그는 동작을 연상시키는 빈 요소를 보존하기 위한 것입니다 ksh. ${array[@]})

a.txt여러 줄이 포함된 경우 zsh명령을 및 루프로 바꿀 수 있습니다 read. 인용된 문자열이 여러 줄에 걸쳐 있으면 각 호출이 여러 줄을 읽을 수 있습니다.content=$(<a.txt)ksh93readwhileread

관련 정보