4개의 명령줄 인수를 허용하는 C 실행 파일이 있습니다.
program <arg1> <arg2> <arg3> <arg4>
텍스트 파일에서 제공하는 인수를 사용하여 실행 파일을 지속적으로 실행하는 셸 스크립트를 만들고 싶습니다. 아이디어는 다음과 같습니다.
./program "$(< arg1.txt)" "$(< arg2.txt)" "$(< arg3.txt)" "$(< arg4.txt)"
실행을 위해 제공된 매개변수는 파일의 각 줄 n
에 있습니다 . n
이렇게 하려고 하면 printf() 호출이 서로 간섭하거나 다른 재미있는 일이 발생합니다. 또한 어떤 방식으로든 매개변수가 구분된 단일 파일만 허용하는 스크립트를 사용할 수도 있습니다.
답변1
while
IFS= read -r a1 <&3 &&
IFS= read -r a2 <&4 &&
IFS= read -r a3 <&5 &&
IFS= read -r a4 <&6
do
./program "$a1" "$a2" "$a3" "$a4" 3<&- 4<&- 5<&- 6<&-
done 3< arg1.txt 4< arg2.txt 5< arg3.txt 6< arg4.txt
파일 중 하나가 소진될 때까지 루프가 실행됩니다. s를 s &&
로 바꾸고 ||
다음까지 실행합니다.모두대신 파일이 소진됩니다(더 짧은 파일의 경우 빈 인수 사용).
GNU를 사용하면 xargs
다음도 수행할 수 있습니다.
paste -d '\n' arg[1-4].txt | xargs -n 4 -r -d '\n' ./program
(주의 사항은 ./program
표준 입력이지만 /dev/null
)
답변2
sed 명령과 Paste 명령의 조합을 살펴보세요. 먼저 붙여넣기를 사용하여 4개 파일을 모두 포함하는 새 스트림을 만듭니다. 그런 다음 sed를 사용하여 원하는 줄을 선택하십시오.
paste arg1.txt arg2.txt arg3.txt arg4.txt | sed -n 10p
붙여넣은 출력의 10번째 줄이 인쇄됩니다. 이는 xargs를 사용하여 프로그램에 인수로 제공될 수 있습니다.
paste arg1.txt arg2.txt arg3.txt arg4.txt | sed -n 10p | xargs ./program
행을 반복하려면 seq 명령을 사용하여 시퀀스를 생성한 다음 시퀀스의 각 값을 반복할 수 있습니다.
for i in $(seq 1 100); do
paste arg1.txt arg2.txt arg3.txt arg4.txt | sed -n ${i}p | xargs ./program
done
이 루프는 각 반복마다 한 번씩 붙여넣기를 호출하므로 속도가 느려집니다. 먼저 임시 파일을 만드는 것이 좋습니다.
답변3
가장 좋은 방법은 파일을 미리 읽고 정리된 결과를 배열이나 임시 파일에 저장하는 것입니다. 그렇지 않으면 각 반복마다 읽기 함수를 4번 호출하고 함수가 파일을 계속해서 읽을 수 있도록 해야 합니다. 이것은 최적이 아닙니다.
임시 파일 버전입니다. 아직 테스트되지 않았습니다.
PROG=./program
TEMPDIR=tmp
mkdir "$TEMPDIR"
# Create the temp files.
for arg in arg*.txt; do
i=0
while read a; do
((i++))
printf "%s\n" "$a" >> "$TEMPDIR"/"$i"
done < "$arg"
done
# Now the temp files are ready.
## Each file contains all arguments for 1 run of ./program,
## each of them on a separate line.
# Start executing the ./program.
for iteration in "$(ls "$TEMPDIR" | sort -n)"; do
unset args
while read arg; do
args=( "$arg" )
done < "$TEMPDIR"/"$iteration"
"$PROG" "${args[@]}"
done
# Finally, remove the temp files.
rm -r "$TEMPDIR"
답변4
Bash(또는 배열을 지원하는 다른 셸)에서 입력 파일에 탭 문자 (*)$''
가 포함되어 있지 않은 한 다음 을 수행할 수 있습니다.
IFS=$'\t'
paste arg1.txt arg2.txt |
while read -r -a A ; do
[ "${#A[@]}" -eq 2 ] && printf "%s - %s\n" ${A[@]}
done
paste
입력 파일을 한 줄씩 연결하고 탭(from)을 구분 기호로 사용하여 read -a A
열을 배열로 읽습니다 . 배열에 정확히 두 개의 구성원이 있는지 확인하고 이를 명령줄에 넣습니다 . 필요에 따라 명령을 변경합니다.A
IFS
[ "${#A[@]}" -eq 2 ]
${A[@]}
printf
(*태그 지원이 필요한 경우 Perl 사용을 권장합니다)
다음 입력 파일을 사용하십시오.
$ cat arg1.txt
foo bar
doo
$ cat arg2.txt
one
two two
three three three
위 코드 조각의 출력은 다음과 같습니다.
foo bar - one
doo - two two
해당 라인이 없기 arg2.txt
때문에 마지막 라인은 무시됩니다 . 어떤 열에 요소가 누락되었는지 신경쓰면 작동하지 않는 선행 탭을 무시하세요.arg1.txt
read