これは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
最後の行に5つの空白を入力して他の場所に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:
このファイルに対して上記のコマンドを実行すると、戻りコードによって一部の行が上書きされ、タブの実際の幅が表示されないため、端末に奇妙な出力が表示されます。
出力で実際の文字を確認するには、8進ダンパに渡しますod
。
x="$(cat filename)"; echo -en "$x" | od -cx
-cが印刷できないエスケープ文字を表示し、-xが対応する16進コード(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.sh
として保存しchmod u+x unescape.sh
て呼び出してみましょう。
./unescape filename.txt outresult.txt
ファイルに NULL 文字がある場合は警告が表示され、NULL は無視されます。