2017-09-08 4 views
1

현재 첨부 파일을 나열된 파일에서 텍스트를 추출하는 다른 스크립트로 보내는 작업을 처리하는 공급 업체 제공 소프트웨어를 사용하고 있습니다. 공급 업체가 제공 한 소프트웨어가 파일 이름을 따옴표로 묶지 않으므로 외부 소스에서 공백을 포함하는 파일을받을 때 스크립트가 실패합니다. 즉, 텍스트 추출 스크립트가 실행될 때 공간에서 분리 될 파일 이름을받습니다 추출기 스크립트에 오류를 일으킬 수 있습니다. 공급 업체가 제공 한 소프트웨어는 우리가 편집 할 수 없습니다.파일 이름에 공백이있는 Linux 스크립팅

이 전체 과정은 자동화 된 전송으로 설계되었으므로 임의로 기어에 던져 질 수있는이 렌치가 문제가됩니다.

텍스트 추출기 스크립트에서 간격을 띄우는 이름을 처리합니다.이 스크립트는 우리가 제어 할 수있는 부분이므로 처리해야합니다. 빠른 Google 후에 스크립트의 IFS 값을 변경하는 것이 빠른 해결책이 될 것 같지만 불행히도 스크립트가 확장 기능이 들어오는 데이터를 손상시킨 후에 적용됩니다.

제가 사용하고있는 스크립트는 -e 값, -i 값 및 -o 값을 취합니다. 이 값은 공급 업체가 제공 한 스크립트에서 보내지 만 편집 권한이 없습니다. 내가 인정

#!/bin/bash 

usage() { echo "Usage: $0 -i input -o output -e encoding" 1>&2; exit 1; } 

while getopts ":o:i:e:" o; do 
    case "${o}" in 
     i) 
      inputfile=${OPTARG} 
      ;; 
     o) 
      outputfile=${OPTARG} 
      ;; 
     e) 
      encoding=${OPTARG} 
      ;; 
     *) 
      usage 
      ;; 
    esac 
done 
shift $((OPTIND-1)) 

... 
... 
<Uses the inputfile, outputfile, and encoding variables> 

, 나는 완전히 이해하지 못하고 이것에 조각이있을 수 있습니다, 그것은 간단한 수정 될 수 있지만, 내 최종 목표는 -o 추출 할 수 있도록, -i 및 -e입니다 각 섹션 내의 공백에 관계없이 모두 1 개의 값을 포함합니다. 파일 이름 값을 추출한 후 스크립트를 인용 처리 할 수 ​​있습니다.

답변

1

해설을 읽고 나면 모든 시나리오에 올바른 대답이 아니지만이 특정 시나리오에 대한 정답은 수동으로 조각을 추출하는 것이 었습니다.

전달할 사전 빌드 된 스크립트를 빌드 중이므로 언제든지 해당 스크립트를 업데이트하지 않으므로이 스크립트는 항상 -i, -o 및 -i를 수신합니다. -e 플래그가 붙어 있고 그 사이에 공백이있어 전달 된 모든 부분이 $*의 다른 변수에 저장됩니다.

그리고 다른 플래그가 참조 될 때까지 플래그 다음의 텍스트가 플래그에 대한 응답이라고 가정 할 수 있습니다. 이것은 우리에게 세 가지 시나리오 잎 :

  1. 변수는 플래그
  2. 변수 즉시 플래그 다음 매개 변수의 첫 번째 조각을 포함 하나 포함을
  3. 변수는 매개 변수의 일부 2+를 포함하고, 이름의 공백은 분할로 해석되었으므로 다시 삽입해야합니다.

내가 계속 달려있는 다른 문제 중 하나는 문자열 리터럴을 IF 문에서 변수와 동일하게하려고하는 것이 었습니다. 이 문제를 해결하기 위해 배열 변수에 모든 관련 데이터를 미리 저장 했으므로 $ variable == $ otherVariable을 테스트 할 수있었습니다.

비록 내가 바꿀 것으로는 생각하지 않지만 우리가 기대하는 것보다 세 가지 깃발이 다른 순서로 나타난다면 우리는해야 할 일을 처리했습니다. (우리가 가정 한 것은 우리가 O, 유감스럽게도 통과 된 것을 볼 수 없다.) 매개 변수는 읽힌 순서대로 배열로 덤프되며, 병렬 배열은 슬롯 0,1,2의 항목이 i, o, e와 관련되는지 여부를 추적합니다.

최종 결과에는 여전히 하나의 결함이 있습니다. 파일 이름에 연속 된 공백이 두 개 이상있는 경우 처리하기 전에 공백을 제거하고 하나의 공간 만 고려할 수 있습니다. 그러나 공간이있는 파일을 처리하기 전에 4000 개 이상의 파일을 처리 할 때마다 하나 이상의 공간이있는 명명 규칙이있을 수 있습니다.

이 시점에서 우리는 어쨌든 드물게 개입해야합니다. 다음과 같이

최종 코드 변경은 다음과 같습니다

#!/bin/bash 
IFS='|' 

position=-1 
ioeArray=("" "" "") 
previous="" 
flagArr=("-i" "-o" "-e" " ") 
ioePattern=(0 1 2) 


#echo "for loop:" 
for i in $*; do 
    #printf "%s\n" "$i" 
    if [ "$i" == "${flagArr[0]}" ] || [ "$i" == "${flagArr[1]}" ] || [ "$i" == "${flagArr[2]}" ]; then 
     ((position += 1)); 
     previous=$i; 
     case "$i" in 
      "${flagArr[0]}") 
      ioePattern[$position]=0 
      ;; 
      "${flagArr[1]}") 
      ioePattern[$position]=1 
      ;; 
      "${flagArr[2]}") 
        ioePattern[$position]=2 
      ;; 
     esac 
     continue; 
    fi 
    if [[ $previous == "-"* ]]; then 
     ioeArray[$position]=${ioeArray[$position]}$i; 
    else 
     ioeArray[$position]=${ioeArray[$position]}" "$i; 
    fi 
    previous=$i; 

done 


echo "extracting (${ioeArray[${ioePattern[0]}]}) to (${ioeArray[${ioePattern[1]}]}) with (${ioeArray[${ioePattern[2]}]}) encoding." 

inputfile=""${ioeArray[${ioePattern[0]}]}""; 
outputfile=""${ioeArray[${ioePattern[1]}]}""; 
encoding=""${ioeArray[${ioePattern[2]}]}""; 
3

게시 한 스크립트 조각에는 인수의 공백과 관련된 문제가 없습니다. (그것이 할당 이후)

다음은, 예를 들어, 인용이 필요하지 않습니다 $inputfile

inputfile=${OPTARG} 

모든 다른 용도를 스크립트 을 인용 더블해야합니다.

중요한 것은이 스크립트가 어떻게 호출되는지입니다.

이 실패하고 변수 inputfilehello을 할당합니다 :

$ ./script.sh -i hello world.txt 

문자열이 world.txt 명령 행 처리를 중지 할 수 getopts 기능을 프롬프트 것하고 스크립트가 될 것 shift (world.txt에 계속 나중에 $1에 남음).

올바르게 문자열을 hello world.txtinputfile를 할당 할 다음

$ ./script.sh -i "hello world.txt" 

같은 것

$ ./script.sh -i hello\ world.txt 
+0

내가 거기에 스크립트를 실행하기 전에이 잡을 수있는 방법이 있습니다,하지만 불행히도,이 스크립트는 내가 수정할 수 없습니다 다른 프로그램에서 호출 이해, 그래서가있다 이 스크립트에 입력 된 후 파일 이름의 분할을 처리합니다. – MeanJerry

+1

@MeanJerry 당신은 _actual_ 문제에 관해 아무 말도하지 않았습니다. 당신은 실제로 문제를 보지 않습니까? 질문에서 마치 당신이 걱정하고있는 것처럼 보입니다. – Kusalananda

+0

@MeanJerry, 당신은 ** "먹이를 먹은 후에"나눌 수 없습니다. 분할은 스크립트가 시작되기 전에 스크립트를 호출하는 프로그램에 의해 수행되고 쉘을 실행하는 쉘이 메모리에 저장되기 전에 수행됩니다. –

1

다음 스크립트는 사용합니다 AWK를 파일 이름에 공백을 포함하면서 인수를 분할 할 수 있습니다. 인수는 어떤 순서로도 될 수 있습니다. 인수에서 여러 개의 연속 된 공백을 처리하지 못하면 인수를 하나로 접습니다.

#!/bin/bash 

IFS=' ' 
str=$(printf "%s" "$*") 

istr=$(echo "${str}" | awk 'BEGIN {FS="-i"} {print $2}' | awk 'BEGIN {FS="-o"} {print $1}' | awk 'BEGIN {FS="-e"} {print $1}') 
estr=$(echo "${str}" | awk 'BEGIN {FS="-e"} {print $2}' | awk 'BEGIN {FS="-o"} {print $1}' | awk 'BEGIN {FS="-i"} {print $1}') 
ostr=$(echo "${str}" | awk 'BEGIN {FS="-o"} {print $2}' | awk 'BEGIN {FS="-e"} {print $1}' | awk 'BEGIN {FS="-i"} {print $1}') 

inputfile=""${istr}"" 
outputfile=""${ostr}"" 
encoding=""${estr}"" 

# call the jar 

자바가 공백이있는 파일 이름에 MalformedUrlException을 던진 jar을 호출 할 때 문제가 발생했습니다.