여러 파일에 공백이 포함된 헤더 줄을 추가하고 싶습니다.
이것이 내가 지금까지 가지고 있는 것입니다:
#!/bin/bash
# script name is "add_header.sh"
# ARG1 = HEADER STRING
# ARG2,3,... = ARRAY OF FILES TO ADD HEADER TO, RELATIVE DIRECTORY
HEADER=$1
shift
for FILE in $@; do
awk -v HEADER=$HEADER FILE=$FILE 'BEGIN{print HEADER} {print}' FILE > FILE.new
done
불행히도 내 사용 사례에서 실행하면 공백으로 인해 실패합니다.
touch file1 file2 file3
./add_header.sh "some header with spaces" file1 file2 file3
그러면 다음과 같은 오류가 발생합니다.
awk: fatal: cannot open file `with' for reading (No such file or directory)
awk: fatal: cannot open file `with' for reading (No such file or directory)
awk: fatal: cannot open file `with' for reading (No such file or directory)
Bash 변수에서 공백을 이스케이프 처리하는 방법이 있습니까? 각 공백 앞에 \를 사용해 보았지만 이제 오류가 다음과 같이 변경됩니다.
./add_header.sh "some\ header\ with\ spaces" file1 file2 file3
awk: fatal: cannot open file `with\' for reading (No such file or directory)
awk: fatal: cannot open file `with\' for reading (No such file or directory)
awk: fatal: cannot open file `with\' for reading (No such file or directory)
이는 공백이 이스케이프되지 않음을 의미합니다.
답변1
#!/bin/sh
header=$1; shift
for pathname do
{ printf '%s\n' "$header"; cat -- "$pathname"; } >"$pathname.new"
done
awk
헤더와 이전 파일 내용을 연결하려고 하므로 여기서는 실제로 필요하지 않습니다 . 간단히 헤더 문자열을 출력한 printf
다음 를 사용하여 파일 내용을 출력하면 cat
됩니다 . printf
출력을 cat
새 파일로 리디렉션 합니다 .
당신은 할 수 있습니다진짜를 사용하여 이를 수행하려면 awk
위 코드와 같이 파일을 반복하거나 awk
명시적인 쉘 루프 없이 각 파일을 처리하도록 할 수 있습니다.
명시적인 쉘 루프가 있는 첫 번째 변형:
#!/bin/sh
header=$1; shift
for pathname do
header=$header awk 'BEGIN { print ENVIRON["header"] }; 1' "$pathname" >"$pathname.new"
done
awk
위의 솔루션은 파일당 한 번 호출 되므로 이 답변의 모든 변형 중에서 가장 느립니다 .
쉘이 없는 루프의 두 번째 변형(GNU처럼 이해해야 함 awk
):BEGINFILE
awk
#!/bin/sh
header=$1; shift
header=$header awk '
BEGINFILE { fname = FILENAME ".new"; print ENVIRON["header"] >(fname) }
{ print >(fname) }' "$@"
세 번째 변형(마지막 코드 조각의 이식 가능한 변형):
#!/bin/sh
header=$1; shift
header=$header awk '
FNR == 1 { fname = FILENAME ".new"; print ENVIRON["header"] >(fname) }
{ print >(fname) }' "$@"
답변2
빈 입력 파일이 없다고 가정하면 올바른 방법은 다음과 같습니다.
#!/usr/bin/env bash
header=$1
shift
awk -v header="$header" '
FNR==1 { close(out); out=FILENAME ".new"; $0=header ORS $0 }
{ print > out }
' "$@"
위 코드는 awk를 사용하는 모든 Unix 시스템의 모든 쉘에서 작동합니다. 빈 입력 파일이 있는 경우 이를 조정해야 합니다.
답변3
나에게 맞는 수정된 버전은 다음과 같습니다.
#!/bin/bash
header=$1
shift
for file in $@; do
awk -v HEADER="$header" 'BEGIN{print HEADER} {print}' "$file" > "$file".new
done
awk 표현식 내에서 사용해 보았지만 {print > [FILE].new}
작동하지 않습니다. 아마도 stdout
awk에서는 새 파일을 생성할 수 없기 때문일 것입니다.