如何在不评估特殊字符的情况下打印文件的内容?

如何在不评估特殊字符的情况下打印文件的内容?

这是一个关于 Bash 和 Linux 的小问题。我有一个包含特殊字符的文件,例如\n\r等等。我正在尝试打印文件而不使用这些特殊字符。例如,如果文件内容是,hi \t hello那么它将按原样打印(而不是hi hello)。使用cat file并不能完成工作。尝试查看 man of cat,我发现我可以使用 -A 选项。它打印:abc^Mabc。但什么是^M?我怎样才能让它按表格打印\<char>

答案1

如果您的文件中包含字面转义的字符,例如,如果“你好\n”有倒斜杠和“t”字母表示应该有一个制表符,而斜杠和“n”应该是换行符,那么您必须解释此表示法并将它们转换为真正的字符。

[正如 Paul Pedant 指出的那样,之前使用 echo 的解决方案不起作用]

经过一些测试,得出了在 Bash 中取消引用字面转义字符的简单方法:

x="$(cat filename)"
echo -en "$x"

为了验证其操作,我创建了此文件(cat > filename然后键入各行,然后Ctrl-D Enter在最后一行中的五个空格后以及其他位置Ctrl-D Enter以关闭文件):

    This line starts with 4 leading spaces, a tab here:\t. Has a real newline (RN) here:
Newline code here:\n, six spaces and a dot:      . RN:
Return code here:\r, because the return code the first three words are hidden in the terminal.RN:
  This line starts with two spaces, then has four and a tab here:    \tRN:
This final line ends with five spaces without an ending newline:     

在此文件上运行上述命令会在我的终端中显示一些奇怪的输出,因为返回代码会导致覆盖部分行并且不显示选项卡的实际宽度。

要检查输出中的实际字符,请将其传递给八进制转储器od

x="$(cat filename)"; echo -en "$x" | od -cx

其中 -c 显示不可打印的转义字符, -x 显示其十六进制代码(TAB=09、RETURN=0D、NEWLINE=0A、SPACE=20 等),结果是:

0000000                   T   h   i   s       l   i   n   e       s   t
           2020    2020    6854    7369    6c20    6e69    2065    7473
0000020   a   r   t   s       w   i   t   h       4       l   e   a   d
           7261    7374    7720    7469    2068    2034    656c    6461
0000040   i   n   g       s   p   a   c   e   s   ,       a       t   a
           6e69    2067    7073    6361    7365    202c    2061    6174
0000060   b       h   e   r   e   :  \t   .       H   a   s       a
           2062    6568    6572    093a    202e    6148    2073    2061
0000100   r   e   a   l       n   e   w   l   i   n   e       (   R   N
           6572    6c61    6e20    7765    696c    656e    2820    4e52
0000120   )       h   e   r   e   :  \n   N   e   w   l   i   n   e
           2029    6568    6572    0a3a    654e    6c77    6e69    2065
0000140   c   o   d   e       h   e   r   e   :  \n   ,       s   i   x
           6f63    6564    6820    7265    3a65    2c0a    7320    7869
0000160       s   p   a   c   e   s       a   n   d       a       d   o
           7320    6170    6563    2073    6e61    2064    2061    6f64
0000200   t   :                           .       R   N   :  \n   R   e
           3a74    2020    2020    2020    202e    4e52    0a3a    6552
0000220   t   u   r   n       c   o   d   e       h   e   r   e   :  \r
           7574    6e72    6320    646f    2065    6568    6572    0d3a
0000240   ,       b   e   c   a   u   s   e       t   h   e       r   e
           202c    6562    6163    7375    2065    6874    2065    6572
0000260   t   u   r   n       c   o   d   e       t   h   e       f   i
           7574    6e72    6320    646f    2065    6874    2065    6966
0000300   r   s   t       t   h   r   e   e       w   o   r   d   s
           7372    2074    6874    6572    2065    6f77    6472    2073
0000320   a   r   e       h   i   d   d   e   n       i   n       t   h
           7261    2065    6968    6464    6e65    6920    206e    6874
0000340   e       t   e   r   m   i   n   a   l   .   R   N   :  \n
           2065    6574    6d72    6e69    6c61    522e    3a4e    200a
0000360       T   h   i   s       l   i   n   e       s   t   a   r   t
           5420    6968    2073    696c    656e    7320    6174    7472
0000400   s       w   i   t   h       t   w   o       s   p   a   c   e
           2073    6977    6874    7420    6f77    7320    6170    6563
0000420   s   ,       t   h   e   n       h   a   s       f   o   u   r
           2c73    7420    6568    206e    6168    2073    6f66    7275
0000440       a   n   d       a       t   a   b       h   e   r   e   :
           6120    646e    6120    7420    6261    6820    7265    3a65
0000460                  \t   R   N   :  \n   T   h   i   s       f   i
           2020    2020    5209    3a4e    540a    6968    2073    6966
0000500   n   a   l       l   i   n   e       e   n   d   s       w   i
           616e    206c    696c    656e    6520    646e    2073    6977
0000520   t   h       f   i   v   e       s   p   a   c   e   s       w
           6874    6620    7669    2065    7073    6361    7365    7720
0000540   i   t   h   o   u   t       a   n       e   n   d   i   n   g
           7469    6f68    7475    6120    206e    6e65    6964    676e
0000560       n   e   w   l   i   n   e   :
           6e20    7765    696c    656e    203a    2020    2020
0000576

不会丢失任何内容,并且代码会转换为所需的单个字符。

问题:这个简单的操作只能转换小文件,因为 Bash 变量的最大长度为 32k 左右。为了扩展这一点,我们必须创建一个循环来读取文件大小合适的块并转换它们。对于此部分块读取,选择的实用程序是dd。这是使用此方法的完整转换器脚本,块大小为 16k (16384):

#!/bin/bash
# unescape.sh: converts escaped chars (\t) to actual chars (TAB)
# 2020.11.19 Fjor
#-------------------------------
[ -z "$2" ] \
    && echo "Use: $0 inputfile outputfile  to unescape chars (\t -> TAB)" \
    && exit
IFILE="$1"
OFILE="$2"

#-- exists input file?
[ ! -r "$IFILE" ] \
    && echo "$0: Can't read inputfile $IFILE" \
    && exit

#-- don't destroy existing output file
[ -f "$OFILE" ] \
    && read -p "$0: Output file $OFILE exists, overwrite(s/n)? " \
    && [ x"$REPLY" != xs ] \
    && exit \
    || rm -f $OFILE

let START=0
let STEP=16384
let SIZE="$(stat -c %s $IFILE)"
let NSTEPS=SIZE/STEP+1

echo -n "Converting..."
for ((n=0 ; n<$NSTEPS ; n++)) ; do
    echo -ne "\r$START bytes converted..."
    #-- ibs input block size, skip N blocks, copy count blocks
    x="$(dd if=$IFILE ibs=$STEP skip=$n count=1 2>/dev/null)"
    echo -ne "$x" >> $OFILE
    let START+=STEP
done 
echo -e "\rConversion complete ($SIZE bytes)." 

#-- end --#

让我们另存为unescape.shchmod u+x unescape.sh并调用它:

./unescape filename.txt outresult.txt

如果文件有 NULL 字符,将出现警告,并且 NULL 将被忽略。

相关内容