태그 보관물: shell

shell

sed -i (in-place editing)로 이식성을 어떻게 얻을 수 있습니까? 백업 사본의 확장이

FreeBSD를 실행하는 공유 호스팅 인 서버용 셸 스크립트를 작성하고 있습니다. 또한 Linux를 실행하는 PC에서 로컬로 테스트하고 싶습니다. 따라서 이식 가능한 방식으로 작성하려고하지만 sed그렇게 할 방법이 없습니다.

내 웹 사이트의 일부는 생성 된 정적 HTML 파일을 사용하며이 sed 행은 각 재생성 후에 올바른 DOCTYPE을 삽입합니다.

sed -i '1s/^/<!DOCTYPE html> \n/' ${file_name.html}

sedLinux에서는 GNU와 함께 작동 하지만 FreeBSD sed-i옵션 이후의 첫 번째 인수 가 백업 사본의 확장이 될 것으로 예상합니다 . 이것이 다음과 같이 보일 것입니다 :

sed -i '' '1s/^/<!DOCTYPE html> \n/' ${file_name.html}

그러나 GNU sed는 그식이 바로 뒤에 이어질 것으로 예상합니다 -i. (또한 개행 처리로 수정해야하지만 이미 여기에 답변되어 있습니다 )

물론 서버의 스크립트 사본에이 변경 사항을 포함시킬 수 있지만 버전 관리를 위해 VCS를 사용하는 것은 혼란 스러울 것입니다. sed로 완전히 이식 가능한 방법으로 이것을 달성 할 수있는 방법이 있습니까?



답변

GNU sed는 이후에 선택적 확장을 허용합니다 -i. 확장은 중간에 공백이없는 동일한 인수에 있어야합니다. 이 구문은 BSD sed에서도 작동합니다.

sed -i.bak -e '…' SOMEFILE

BSD에서는 -i입력 파일이 여러 개인 경우 동작이 변경됩니다. 파일은 독립적으로 처리됩니다 (예 : $각 파일의 마지막 행과 일치). 또한 이것은 BusyBox에서 작동하지 않습니다.

백업 파일을 사용하지 않으려면 사용 가능한 sed 버전을 확인할 수 있습니다.

case $(sed --help 2>&1) in
  *GNU*) set sed -i;;
  *) set sed -i '';;
esac
"$@" -e '…' "$file"

또는 대안으로 위치 매개 변수가 방해되지 않도록 함수를 정의하십시오.

case $(sed --help 2>&1) in
  *GNU*) sed_i () { sed -i "$@"; };;
  *) sed_i () { sed -i '' "$@"; };;
esac
sed_i -e '…' "$file"

귀찮게하지 않으려면 Perl을 사용하십시오.

perl -i -pe '…' "$file"

이식 가능한 스크립트를 작성하려면 사용하지 마십시오 -i. POSIX에는 없습니다. sed가 수행하는 작업을 수동으로 수행하십시오. 한 줄만 더하면됩니다.

sed -e '…' "$file" >"$file.new"
mv -- "$file.new" "$file"


답변

sed플레이를 멋지게 만드는 요령을 찾지 못하면 다음을 시도해보십시오.

  1. 사용하지 마십시오 -i:

    sed '1s/^/<!DOCTYPE html> \n/' "${file_name.html}" > "${file_name.html}.tmp" &&
      mv "${file_name.html}.tmp" "${file_name.html}"
  2. 펄 사용

    perl -i -pe 'print "<!DOCTYPE html> \n" if $.==1;' "${file_name.html}"

답변

에드

항상 ed기존 파일 앞에 줄을 추가하는 데 사용할 수 있습니다 .

$ printf '0a\n<!DOCTYPE html>\n.\nw\n' | ed my.html

세부

주위의 비트 <!DOCTYPE html>ed해당 행을 파일에 추가 하도록 지시하는 명령 my.html입니다.

sed

이 명령을 sed사용할 수도 있다고 생각합니다 .

$ sed -i '1i<!DOCTYPE html>\n` testfile.csv


답변

perl -i후드에서 수행하는 작업을 수동으로 수행 할 수도 있습니다 .

{ rm -f file && { echo '<!DOCTYPE html>'; cat; } > file;} < file

마찬가지로 perl -i백업이 없으며 여기에 제공된 대부분의 솔루션과 마찬가지로 파일의 권한, 소유권에 영향을 줄 수 있으며 심볼릭 링크를 일반 파일로 바꿀 수 있습니다.

와:

sed '1i\
<!DOCTYPE html>' file 1<> file

sed파일 자체를 덮어 쓰므로 소유권과 권한 또는 심볼릭 링크에 영향을 미치지 않습니다. 일반적으로 명령으로 덮어 쓰기 전에 (내 경우에는 4k)에서 데이터로 가득 찬 버퍼를 읽었 sed으므로 GNU와 함께 작동합니다 . 파일이 출력을 버퍼링 한다는 사실을 제외하고 파일이 4k를 초과하면 작동하지 않습니다 .sedfileised

기본적으로 sed읽기 및 쓰기를 위해 4k 블록에서 작동합니다. 삽입 할 줄이 4k보다 작 으면 sed아직 읽지 않은 블록을 덮어 쓰지 않습니다.

나는 그것에 의존하지 않을 것입니다.


답변

Mac OS X에서도 사용되는 FreeBSD sed 는 다음 (regex) 명령을 정확하고 명확하게 정의하고 인식하기 -e위해 -i스위치 뒤에 옵션이 필요합니다 .

즉, sed -i -e ...FreeBSD & GNU 모두에서 작동해야합니다 sed.

보다 일반적으로 FreeBSD 이후 백업 확장을 생략 sed -i하려면 명령 행 인수를 구문 분석하는 동안 FreeBSD의 일부에서 혼동을 피하기 위해 sed다음과 같은 명시적인 옵션 또는 스위치 가 필요합니다 .-ised

그러나, sed내부 파일 편집은 파일 inode 변경으로 이어집니다 (파일의 “제자리”편집 참조 ).

일반적인 힌트로, 최신 버전의 FreeBSD sed에는 -rGNU와의 호환성을 높이는 스위치가 sed있습니다.

echo a > testfile.txt
ls -li testfile.txt
#gsed -i -e 's/a/A/' testfile.txt
#bsdsed -i 's/a/A/' testfile.txt  # does not work
bsdsed -i -e 's/a/A/' testfile.txt
ls -li testfile.txt
cat testfile.txt


답변

sed -i경쟁 조건을 최대한 피하면서 단일 파일을 이식 가능하게 에뮬레이트하려면 다음을 수행하십시오.

sed 'script' <<FILE >file
$(cat file)
FILE

그건 그렇고, 이것은 sed -i디렉토리 및 파일 권한에 따라 sed -i사용자가 편집 권한이없는 파일을 덮어 쓸 수있게하는 가능한 문제를 처리합니다 .

다음과 같은 백업을 수행 할 수도 있습니다.

sed 'script' <<FILE >file
$(tee file.old <file)
FILE


답변

Ex 모드에서 Vim을 사용할 수 있습니다 :

ex -sc '1i|<!DOCTYPE html>' -cx file
  1. 1 첫 줄을 선택하십시오

  2. i 텍스트와 개행 삽입

  3. x 저장하고 닫습니다

또는 주석에서와 같이 평범한 오래된 표준 ex :

printf '%s\n' 1i '<!DOCTYPE html>' . x | ex file