명령 대체: 줄바꿈으로 분할하지만 공백으로 분할하지 않음

명령 대체: 줄바꿈으로 분할하지만 공백으로 분할하지 않음

이 문제를 여러 가지 방법으로 해결할 수 있다는 것을 알고 있지만, bash 내장 기능만 사용하여 이 문제를 해결할 수 있는 방법이 있는지, 그렇지 않다면 가장 효율적인 방법은 무엇인지 알고 싶습니다.

다음 내용이 포함된 파일이 있습니다.

AAA
B C DDD
FOO BAR

내 말은 여러 줄이 있고 각 줄에는 공백이 있을 수도 있고 없을 수도 있다는 것입니다. 이런 명령을 실행하고 싶습니다

cmd AAA "B C DDD" "FOO BAR"

내가 사용하면 cmd $(< file)나는 얻는다.

cmd AAA B C DDD FOO BAR

내가 사용하면 cmd "$(< file)"나는 얻는다.

cmd "AAA B C DDD FOO BAR"

각 줄이 하나의 매개변수만 처리하도록 하려면 어떻게 해야 합니까?

답변1

가지고 다닐 수 있는:

set -f              # turn off globbing
IFS='
'                   # split at newlines only
cmd $(cat <file)
unset IFS
set +f

또는 하위 쉘을 사용하여 IFS및 옵션 변경 사항을 현지화합니다.

( set -f; IFS='
'; exec cmd $(cat <file) )

쉘은 큰따옴표 없이 변수 또는 명령 대체 결과에 대해 필드 분할 및 파일 이름 생성을 수행합니다. 따라서 를 사용하여 파일 이름 생성을 끄고 필드를 구분하는 줄 바꾸기만 포함 set -f하도록 필드 분할을 구성해야 합니다 .IFS

bash 또는 ksh 구성을 사용하면 큰 이점이 없습니다. IFS함수를 현지화 할 수 있지만 set -f.

Bash 또는 ksh93에서는 필드를 여러 명령에 전달해야 하는 경우 배열에 필드를 저장할 수 있습니다. 어레이를 구축할 때 크기 조정을 제어해야 합니다. 그런 다음 "${a[@]}"각 단어마다 하나씩 배열의 요소를 확장합니다.

set -f; IFS=$'\n'
a=($(cat <file))
set +f; unset IFS
cmd "${a[@]}"

답변2

임시 배열을 사용하여 이를 수행할 수 있습니다.

설정:

$ cat input
AAA
A B C
DE F
$ cat t.sh
#! /bin/bash
echo "$1"
echo "$2"
echo "$3"

배열을 채웁니다:

$ IFS=$'\n'; set -f; foo=($(<input))

배열을 사용하십시오:

$ for a in "${foo[@]}" ; do echo "--" "$a" "--" ; done
-- AAA --
-- A B C --
-- DE F --

$ ./t.sh "${foo[@]}"
AAA
A B C
DE F

임시 변수 없이 이 작업을 수행할 수 있는 방법은 없습니다. 변경 사항이 IFS중요하지 않은 cmd경우는 다음과 같습니다.

$ IFS=$'\n'; set -f; cmd $(<input) 

그것은 이루어져야합니다.

답변3

bash이를 수행하는 정식 방법 은 다음과 같습니다 .

unset args
while IFS= read -r line; do 
    args+=("$line") 
done < file

cmd "${args[@]}"

또는 귀하의 bash 버전에 다음이 포함된 경우 mapfile:

mapfile -t args < filename
cmd "${args[@]}"

매핑 파일과 읽는 동안 루프와 한 줄 루프 사이에서 찾을 수 있는 유일한 차이점

(set -f; IFS=$'\n'; cmd $(<file))

전자는 빈 줄을 빈 인수로 변환하는 반면, 단일 라이너는 빈 줄을 무시합니다. 이 경우 어쨌든 나는 한 줄 동작을 선호하므로 그 간결함은 두 배의 이점입니다.

를 사용하겠지만 , 적용되기 전에 명령줄을 구성하는 것으로 해석되기 IFS=$'\n' cmd $(<file)때문에 작동하지 않습니다 .$(<file)IFS=$'\n'

내 경우에는 작동하지 않았지만 이제 많은 도구가 null (\000)대신 줄 종료를 지원한다는 것을 알게 되었습니다 newline (\n). 이는 다음과 같은 경우의 일반적인 원인인 파일 이름을 처리할 때 많은 작업을 더 쉽게 만듭니다.

find / -name '*.config' -print0 | xargs -0 md5

와일드카드나 보간 또는 기타 작업 없이 md5에 인수로 정규화된 파일 이름 목록을 제공합니다. 이로 인해 내장되지 않은 솔루션이 탄생했습니다.

tr "\n" "\000" <file | xargs -0 cmd

빈 줄도 무시하지만 공백만 있는 줄은 캡처합니다.

답변4

old=$IFS
IFS='  #newline
'
array=`cat Submissions` #input the text in this variable
for ...  #use parts of variable in the for loop
... 
done
IFS=$old

내가 찾을 수 있는 가장 좋은 방법. 정상적인 일.

관련 정보