다음과 같은 월 목록을 사용하는 간단한 스크립트를 만들려고 합니다.
(1월 2월)
이 명령을 생성하고 실행하려면 다음을 수행하십시오.
python ExpenseManager.py -p 입력/2019년 1월\ Debit.CSV 입력/2019년 1월\ Credit.CSV -p 입력/2019년 2월\ Debit.CSV 입력/2019년 2월\ Credit.CSV
이를 위해 제가 작성한 프로그램은 다음과 같습니다.
#!/usr/bin/env bash
clear
months=(Jan Feb)
args=()
for month in ${months[@]}; do
args=(${args[@]} -p "Inputs/${month}\\ 2019\\ Debit.CSV" "Inputs/${month}\\ 2019\\ Credit.CSV")
done
python ExpenseManager.py "${args[@]}"
exit 0
이론적으로는 이것이 작동합니다. 결과 명령을 에코하면 원하는 정확한 명령을 얻을 수 있습니다.
python ExpenseManager.py -p 입력/2019년 1월\ Debit.CSV 입력/2019년 1월\ Credit.CSV -p 입력/2019년 2월\ Debit.CSV 입력/2019년 2월\ Credit.CSV
이제 프로그램에서 생성된 명령을 복사/붙여넣기하여 실행하면 제대로 작동합니다. 그러나 Bash에 명령 실행을 요청하면 Bash에 이스케이프된 백슬래시를 포함하는 데 사용하는 백슬래시가 포함됩니다.
Namespace(filepairs=[['Input/January\', '2019\', 'Debit.CSV', 'Input/January\', '2019\', 'Credit.CSV'], ['Input /February\2019 \Debit.CSV', '2019년 2월 입력\Credit.CSV']]
나는 그것을 작동시키기 위해 여러 가지 해결책을 시도했습니다.
매개변수를 단일 문자열로 만들고 그 위에 구축해 보았습니다.
다음과 같이 매개변수를 작은따옴표로 묶고 공백 주위에 큰따옴표를 사용해 보았습니다.
args=(${args[@]} -p '입력/${월}" "2019" "Debit.CSV "입력/${월}" "2019" "Credit.CSV")
- 다음과 같이 공백이 필요한 인수의 각 부분을 구분하기 위해 따옴표를 사용해 보았습니다.
args=(${args[@]} -p "Inputs/${month}" "2019" "Debit.CSV" "Inputs/${month}\ 2019\ Credit.CSV")
여기와 다른 곳에서 다른 솔루션을 살펴봤지만 아무 것도 작동하지 않는 것 같습니다. 따라서 계속해서 이 문제에 얽매이는 대신, 누군가 Bash가 프로그래밍 방식으로 구축된 보간 명령을 실행하게 만드는 마술을 말해 줄 수 있기를 바랍니다.
답변1
echo
어떤 명령이 실행되고 있는지 확인하는 데 사용하지 마십시오 . 명령을 인쇄합니다뒤쪽에구문 분석됨, 즉 따옴표를 적용하고 이스케이프 처리한 후삭제하고echo
) 따라서 원본 명령줄(예: 구문 분석 전)에서 볼 수 있는 것처럼 의 출력에 따옴표 및/또는 이스케이프가 포함되어 있는 경우 이는 심각한 오류를 나타냅니다. 다음 두 명령의 출력을 비교하십시오 echo
.
$ month=Jan
$ var="Inputs/${month}\\ 2019\\ Debit.CSV"
$ echo $var
Inputs/Jan\ 2019\ Debit.CSV
$ echo Inputs/Jan\ 2019\ Debit.CSV
Inputs/Jan 2019 Debit.CSV
먼저 이스케이프 문자를 인쇄하여 다음을 나타냅니다.아니요구문 분석하고 적용하고 삭제합니다. 두 번째 예에서는 사라져서 다음을 나타냅니다.예구문 분석하고 적용하고 삭제합니다.
그렇다면 어떻게 해결해야 할까요? 두 가지 규칙: 1) 변수에 따옴표나 이스케이프를 추가하지 마십시오(문자열이 추가 구문 분석 수준을 거치는 이상한 경우 제외). 2) 대신 모든 변수 참조 주위에 큰따옴표를 추가하십시오(포함 ${args[@]}
). 몇 가지 이상한 예외). 또는 를 사용하여 배열에 추가할 수 있습니다 array+=("new" "elements")
.
고정된 스크립트는 다음과 같습니다.
#!/usr/bin/env bash
clear
months=(Jan Feb)
args=()
for month in "${months[@]}"; do
args+=(-p "Inputs/${month} 2019 Debit.CSV" "Inputs/${month} 2019 Credit.CSV")
done
python ExpenseManager.py "${args[@]}"
exit 0