공백이 포함된 문자열 보간을 사용하여 bash 스크립트에서 명령을 절차적으로 생성하는 방법은 무엇입니까?

공백이 포함된 문자열 보간을 사용하여 bash 스크립트에서 명령을 절차적으로 생성하는 방법은 무엇입니까?

다음과 같은 월 목록을 사용하는 간단한 스크립트를 만들려고 합니다.

(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

관련 정보