이 문제를 여러 가지 방법으로 해결할 수 있다는 것을 알고 있지만, 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
내가 찾을 수 있는 가장 좋은 방법. 정상적인 일.