쉼표로 구분된 값이 있는 Bash 스크립트 변수는 다른 파일에 추가될 때 쉼표로 구분되지 않습니다.

쉼표로 구분된 값이 있는 Bash 스크립트 변수는 다른 파일에 추가될 때 쉼표로 구분되지 않습니다.

테이블 항목의 유효성을 검사하는 bash 스크립트가 있습니다. 최종 출력 값은 $out이며 SQL INSERT 문에 삽입된 후 /tmp/crew.txt에 추가됩니다. $out은 명확하게 쉼표로 구분되어 있지만 /tmp/crew.txt의 결과 INSERT 문의 값 사이에는 쉼표가 없습니다. 이런 경우가 발생하는 이유는 무엇이며 /tmp/crew.txt에 쉼표로 구분된 값이 있도록 수정하려면 어떻게 해야 합니까?

#!/bin/bash

out=290,'02:20:00','02:40:00',20.5,NULL

echo "${out:1}"

290,'02:20:00','02:40:00',20.5,NULL


echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt
vi /tmp/crew.txt

INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ( 290 '02:20:00' '02:40:00' 20 NULL);

따라서 /tmp/crew.txt의 결과는 다음과 같아야 합니다.

INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ( 290,'02:20:00','02:40:00',20,NULL);

답변1

가설: IFS변수에 가 포함되어 있습니다 ,. 스크립트는 를 변경하지 않으므로 IFS기본값이 아닌 값이 환경에 있어야 합니다.

이 다른 답변${out:1}다음과 같은 줄에서 인용이 해제된 것을 확인했습니다 .

echo "foo"${out:1}"bar"

인용되지 않은 변수단어 분할 및 파일 이름 생성을 거칩니다.. 단어 분할은 IFS. 따옴표가 없는 것은 ${out:1}여러 단어로 분할되어 echo여러 인수를 가져와 단일 공백으로 구분하여 인쇄합니다(이것이 echo에 관계없이 수행되는 작업이기 때문입니다 IFS).

사용한 경우printf 조언대로, 변수가 인용되었는지 확인하는 것이 더 쉬울 것입니다.

printf 'INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (%s);\n' "${out:1}"

변수를 큰따옴표로 묶지 않으면 printf에서 여러 인수를 가져오고 ${out:1}여러 줄이 생성됩니다. 그러면 일부 분할이 발생하는 것이 분명해집니다. 이를 사용하면 echo주장을 연결하여 이 사실을 어느 정도 난독화할 수 있습니다.


별도의 문제:

  • 원하는 출력은 원하지 않지만 "${out:1}"앞에 " $out"공백이 있음을 나타냅니다.

  • 변수에 작은따옴표를 포함하려면 쉘이 이를 제거하지 않도록 해야 합니다. 탈출하세요 (크레딧은이미 언급한 답변) 또는 큰따옴표로 묶으십시오.

    out="290,'02:20:00','02:40:00',20.5,NULL"
    

답변2

왜 이런 일이 발생하며 어떻게 해결할 수 있습니까?

스크립트에서 에코된 출력과 빈 줄을 제거하면 다음과 같은 정리된 스크립트가 제공됩니다.

#!/bin/bash
out=290,'02:20:00','02:40:00',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt

그래도 해당 스크립트를 실행하면ShellCheck – 쉘 스크립트 분석 도구다음 오류가 발생합니다.

$ shellcheck myscript
 
Line 4:
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES ("${out:1}");" >> /tmp/crew.txt
>>                                                                                      ^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.

$ 

제안된 오류 수정으로 따옴표를 제거하면 이제 다음과 같은 결과를 얻을 수 있습니다.

#!/bin/bash
out=290,'02:20:00','02:40:00',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> /tmp/crew.txt

echo "${out:1}"그러나 이것을 실행해도 작은 따옴표가 '에 저장되지 않았 out으며 이스케이프해야 함을 알 수 있듯이 여전히 올바른 답을 얻을 수 없습니다 .

$ test.sh
90,02:20:00,02:40:00,20.5,NULL
$

이 문제를 해결하면 다음이 제공됩니다.

#!/bin/bash
out=290,\'02:20:00\',\'02:40:00\',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> test.txt

참고 출력 파일 이름을 다음으로 변경했습니다.test.txt

테스트:

$ test.sh
90,'02:20:00','02:40:00',20.5,NULL
$ cat test.txt
INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (90,'02:20:00','02:40:00',20.5,NULL);
$

따라서 스크립트의 최종 수정 버전은 다음과 같습니다.

#!/bin/bash
out=290,\'02:20:00\',\'02:40:00\',20.5,NULL
echo "${out:1}"
echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> >> /tmp/crew.txt

여기에서 깨진 스크립트를 디버깅하는 방법에 대한 강의가 끝납니다.

답변3

나에게 맞는 해결책은 다음 INSERT 문을 에코하는 것입니다.

echo "INSERT INTO tip_run (date_linkid, start_time, finish_time, weight, note) VALUES (${out:1});" >> /tmp/crew.txt

탈출이 필요하지 않습니다. 그러나 그 이유는 확실하지 않습니다.

관련 정보