파일의 문자 바꾸기

파일의 문자 바꾸기

안녕하세요, 저는 2개의 기호를 가져와 첫 번째 기호를 두 번째 기호로 바꾸는 스크립트를 작성 중입니다. 스크립트는 이를 매개변수 파일로도 사용합니다. 아이디어는 파일의 첫 번째 문자를 두 번째 문자로 바꾸는 것입니다. 스크립트는 다음과 같습니다.

char_src=$1
char_dest=$2
shift

for file
do
    while read -r line
    do
        line=${line//$char_src/$char_dest}
        echo "$line"
    done < "$file"
done

문제는 올바른 내용을 인쇄하지만 변경 사항을 파일에 저장하지 않는다는 것입니다. done < "$file"

답변1

먼저 쉬운 부분: 쉘에서 파일을 한 줄씩 읽는 것이 느리므로 대신 이것을 사용할 수 있습니다 tr. man tr자세히보다.

둘째, 임시 파일이 필요합니다. 파일을 동시에 읽고 쓸 수는 없습니다(어차피 쉘에서는 불가능). 따라서 다음과 같이 해야 합니다.

tr -- "$1" "$2" <"$file" >"$file".tmp
mv -f -- "$file".tmp "$file"

분명한 질문은 tr어떤 이유로든(예: $1비어 있는 경우) 실패하면 어떻게 되는지입니다. 그런 다음 $file.tmp여전히 생성된 다음(쉘이 행을 구문 분석할 때 생성됨) $file대체됩니다.

따라서 더 안전한 접근 방식은 다음과 같습니다.

tr -- "$1" "$2" <"$file" >"$file".tmp && \
mv -f -- "$file".tmp "$file"

이제 $file성공한 경우에만 교체됩니다.tr

하지만 주변에 다른 파일 이름이 있으면 어떻게 될까요 $file.tmp? 글쎄, 그것은 다루어질 것이다. 여기서 상황이 더욱 복잡해집니다. 기술적으로 올바른 방법은 다음과 같습니다.

tmp="$( mktemp -t "${0##*/}"_"$$"_.XXXXXXXX )" && \
trap 'rm -f "$tmp"' EXIT HUP INT QUIT TERM || exit 1
tr -- "$1" "$2" <"$file" >"$tmp" && \
cat -- "$tmp" >"$file" && \
rm -f -- "$tmp"

이렇게 하면 mktemp임시 파일이 생성됩니다. trap스크립트가 정상적으로 또는 비정상적으로 종료되면 파일이 정리되고 cat -- "$tmp" >"$file"대신 권한 mv$file유지됩니다. 쓰기 권한이 없으면 $file여전히 실패할 수 있지만 임시 파일은 결국 삭제됩니다.

또는 GNU에는 sed파일을 그 자리에서 편집할 수 있는 옵션이 있으므로 다음을 수행할 수 있습니다.

sed -i "s/$1/$2/g" "$file"

그러나 이는 보기만큼 간단하지 않습니다. $1또는 for가 특별한 의미를 갖는 경우 $2위 작업은 실패합니다 sed. 따라서 먼저 이스케이프해야 합니다.

in=$(  printf '%s\n' "$1" | sed 's:[][\/.^$*]:\\&:g' )
out=$( printf '%s\n' "$2" | sed 's:[\/&]:\\&:g;$!s/$/\\/' )
sed -i "s/$in/$out/" "$file"

답변2

이 목적을 위해 특별히 제작된 도구가 있다는 사실은 지금은 무시하세요.

char_src=$1
char_dest=$2
shift

shift 2여기서 일반 파일을 shift이동 $2하고 $1첫 번째 파일 이름을 남겨두기를 원할 수 있습니다 .

    while read -r line

올바르게 사용하고 있지만 read -r기본값을 사용하면 IFS앞뒤 read공백이 제거됩니다.

    done < "$file"

<리디렉션 전용입력하다, 필요한 출력을 리디렉션 > "$file2"하고 여러 위치에 명시된 대로(예를 들어 여기), 동일한 파일로 리디렉션하면 아무것도 읽기 전에 파일이 잘립니다.

이를 위해 만들어진 도구는 단일 문자를 다른 단일 문자로 변경하려면 를 사용하십시오 tr. 쉘 ${var//pat/repl}구성은 전체 문자열을 대체하며 s/pat/repl/gin 와 더 유사합니다 sed.

관련 정보