생성을 제어할 수 없는 잘못된 xml 문자를 제거하기 위해 문자별로 파일을 필터링하고 싶지만 한 파일에서 다른 파일로 단일 문자를 복사할 수도 없는 것 같습니다. 예전에는 캐리지 리턴을 포함한 텍스트 부분을 복사 했지만 printf
이제는 캐리지 리턴을 하나로 복사하지 않고 빈 길이의 문자열로 복사합니다. 내 코드:
infile=$1
outfile=$2
touch $outfile
while IFS= read -r -n1 char
do
# display one character at a time
printf "%s" "$char" >> $outfile
done < "$infile"
diff $infile $outfile
sed나 awk를 사용해도 상관없지만 허용되는 문자를 인코딩해야 합니다.
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
답변1
입력에는 문제가 없으며 read
정상적으로 읽어야 합니다. 개행(newline) 문자는 이기 때문입니다 read
. 이 read -d ''
트릭을 사용하면 작동하게 됩니다.
echo $'\r' | { IFS= read -r -n1 x; echo "$x"|xxd; } # CR
echo $'\n' | { IFS= read -r -n1 x; echo "$x"|xxd; } # LF fails
echo $'\n' | { IFS= read -d '' -r -n1 x; echo "$x"|xxd; } # LF ok
그러나 그들이 말했듯이 아마도 쉘에서는 그런 일을 하고 싶지 않을 것입니다. tr
고정된 문자 집합을 제거하는 데 필요한 것이 바로 이것이지만, 적어도 GNU는 tr
문자가 아닌 바이트로 작동하므로 유니코드에서는 많이 사용되지 않습니다.
내 생각에 이 Perl은 로케일이 UTF-8로 올바르게 설정된 경우 UTF-8 데이터에 대해 작동해야 한다고 생각합니다.
perl -C -pe 'tr/\x09\x0a\x0d\x20-\x{d7ff}\x{e000}-\x{fffd}\x{10000}-\x{10ffff}//cd' < in > out
하지만 테스트해 보는 것이 좋을 것 같습니다. 저는 유니코드 문제에 익숙하지 않습니다.
tr/abc//cd
abc
(에 나열되지 않은 문자를 제거하면 tr///
실제로 문자가 다른 문자로 변환됩니다.perlop
). 문자 목록과 범위를 허용하고 16진수 값으로 문자를 나타냅니다.\xHH
헤헤, 그리고 귀중한\x{HHHH}
하하하하. 따라서 위의 내용은 0x09
, 0x0a
, 0x0d
, 등 0x20
의 모든 것을 허용합니다.0xd7ff
위 목록은 질문에 제공된 목록에서 직접 가져온 것입니다. 이것이 변경되어야 하는지 여부는 최종 사용자에게 맡기겠습니다.