如何在 bash 中从文件中打印文字字符?

如何在 bash 中从文件中打印文字字符?

我想按字符过滤文件(为了删除我无法控制生成的无效 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应该可以正常读取。换行符(换行符)是,因为它是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

但是,正如他们所说,您可能不想在 shell 中做这样的事情。tr这正是删除一组固定字符所需的,但至少 GNUtr适用于字节,而不是字符,因此它对 Unicode 没有多大用处。

我认为这个 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

但最好测试一下,我不太习惯 Unicode 怪癖。

tr/abc//cdabc删除(中未列出的字符tr///实际上是将字符转换为其他字符,请参见perlop)。它接受字符列表以及范围,并表示具有十六进制值的字符\xHH赫赫,以及一个有价值的\x{HHHH}呵呵呵呵。所以上面接受0x09, 0x0a, 0x0d, 从0x200xd7ff等的所有内容。

上面的列表直接取自问题中提供的列表。我将把它留给最终用户来评估是否应该更改。

相关内容