
테이블 항목의 유효성을 검사하는 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
탈출이 필요하지 않습니다. 그러나 그 이유는 확실하지 않습니다.