パターンに応じて「1行のテキスト」を分割する方法は? [閉鎖]

パターンに応じて「1行のテキスト」を分割する方法は? [閉鎖]

グラフィック以外の文字を含む1行のファイルがありますが、パターンに基づいて分割したいと思います。私のパターンは \[0-9][0-9][0-9];私は何をしますか?たとえば、次の行を分割したいとします。

\001abd \002pqr \003xyz

到着する:

\001abd 
\002pqr 
\003xyz

私は/bin/shをデフォルトのシェルとして使用します。

別の入力例:

CHANGE^\039^OE@ MORE^\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020

希望の出力:

CHANGE^
\039^OE@ MORE^
\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^
\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020

1行のファイルサイズは80KBで、GNU sedバージョン4.2.1を使用しており、オペレーティングシステムはRed Hat Enterprise Linux Serverバージョン6.5(San Diego)です。

答え1

予備的な問題文があり、様々な解決策が提案されている。実際のデータが説明と一致しないため、これは機能しないことがわかりました。

考えられる答え

私のパターンは次のとおりです。FS[0-9][0-9][0-9](FSは「フィールド区切り文字」です。)これをスクリプトでどのように使用できますかsed

BashとBSDの場合、sedこれを使用できます(これはジョン1024 提案済みBSDとMac OS Xを使ってsed-E拡張正規表現記号を有効にする):

sed -E $'s/(.)(\x1C[[:digit:]]{3})/\\1\\\n\\2/g' file1

記号$'…'はBashです。ANSI C見積もり器具。 FSのバイト値は、28、16進数0x1C、または8進数038です。二重バックスラッシュについてはsedバックスラッシュをご覧ください。\n前の内容は、マニュアル(このセクション)の規定を\\満たしています。seds///

改行を置き換えて行を分割できます。代替文字列に改行文字を指定するには、その前にバックスラッシュを追加します。

GNUで何が機能しているかを確認してくださいsed

また、FSが時々次のようにエンコードされることを観察しましたControl-BackslashControl-Aコード1がありますが、Aコード65 = 64 + 1があり、バックスラッシュには\コード92 = 64 + 28があるため)。いつも学生質問に混乱があります。

GNUを参照してくださいsed-rBSDが実行する操作を実行するために使用されます-Esedいかなる種類のシンボルも認識されません。

研究背景

ファイルをメールで送信しました。受け取った内容が正しい場合は、必要な内容の別の説明が必要です。

単語数出力:

$ wc file1
       1    8804   80106 file1
$

16進ダンプの出力は次のとおりです。

$ odx file1 | sed 20q
0x0000: 33 1C 1C 1C 31 31 1C 30 30 31 0E 32 30 31 1C 30   3...11.001.201.0
0x0010: 30 32 0E 32 30 31 1C 30 30 33 0E 32 30 33 1C 30   02.201.003.203.0
0x0020: 30 34 24 20 1C 30 30 35 0E 30 30 32 1C 30 30 36   04$ .005.002.006
0x0030: 0E 30 30 32 1C 30 31 31 0C 1B 28 32 0F 45 40 20   .002.011..(2.E@ 
0x0040: 20 20 59 4F 55 52 20 43 41 52 44 20 49 53 20 4E     YOUR CARD IS N
0x0050: 4F 54 20 20 53 45 52 56 49 43 45 44 0F 46 40 20   OT  SERVICED.F@ 
0x0060: 20 20 20 20 20 20 20 20 20 42 59 20 20 54 48 49            BY  THI
0x0070: 53 20 41 54 4D 20 0F 47 40 20 20 20 20 20 50 4C   S ATM .G@     PL
0x0080: 45 41 53 45 20 54 41 4B 45 20 20 59 4F 55 52 20   EASE TAKE  YOUR 
0x0090: 43 41 52 44 1B 28 37 0F 49 40 20 20 20 20 20 20   CARD.(7.I@      
0x00A0: 20 5C 26 20 2D 28 23 58 3E 3D 20 5C 25 22 40 22    \& -(#X>= \%"@"
0x00B0: 20 41 22 20 0F 4A 40 20 20 20 20 20 20 20 30 57    A" .J@       0W
0x00C0: 5F 40 5B 3F 4A 58 20 2D 28 40 23 51 20 59 5F 22   _@[?JX -(@#Q Y_"
0x00D0: 20 0F 4B 40 20 20 30 3E 5F 40 22 3E 40 26 20 22    .K@  0>_@">@& "
0x00E0: 40 20 3E 5B 3D 20 20 2D 28 40 23 51 20 23 4D 47   @ >[=  -(@#Q #MG
0x00F0: 55 1B 28 32 1C 30 31 34 0C 1B 28 3E 0F 43 40 20   U.(2.014..(>.C@ 
0x0100: 20 20 45 53 50 2D 4C 49 4E 4B 2F 46 54 53 0F 45     ESP-LINK/FTS.E
0x0110: 40 20 20 20 20 20 20 20 41 54 4D 0F 47 40 20 4D   @       ATM.G@ M
0x0120: 41 52 4B 45 54 49 4E 47 20 4D 45 53 53 41 47 45   ARKETING MESSAGE
0x0130: 20 45 32 1C 30 31 35 0C 1C 30 31 38 0C 1C 30 32    E2.015..018..02
$

以下は同じデータですod -c

$ od -c file1 | sed 20q
0000000    3 034 034 034   1   1 034   0   0   1 016   2   0   1 034   0
0000020    0   2 016   2   0   1 034   0   0   3 016   2   0   3 034   0
0000040    0   4   $     034   0   0   5 016   0   0   2 034   0   0   6
0000060  016   0   0   2 034   0   1   1  \f 033   (   2 017   E   @    
0000100            Y   O   U   R       C   A   R   D       I   S       N
0000120    O   T           S   E   R   V   I   C   E   D 017   F   @    
0000140                                        B   Y           T   H   I
0000160    S       A   T   M     017   G   @                       P   L
0000200    E   A   S   E       T   A   K   E           Y   O   U   R    
0000220    C   A   R   D 033   (   7 017   I   @                        
0000240        \   &       -   (   #   X   >   =       \   %   "   @   "
0000260        A   "     017   J   @                               0   W
0000300    _   @   [   ?   J   X       -   (   @   #   Q       Y   _   "
0000320      017   K   @           0   >   _   @   "   >   @   &       "
0000340    @       >   [   =           -   (   @   #   Q       #   M   G
0000360    U 033   (   2 034   0   1   4  \f 033   (   > 017   C   @    
0000400            E   S   P   -   L   I   N   K   /   F   T   S 017   E
0000420    @                               A   T   M 017   G   @       M
0000440    A   R   K   E   T   I   N   G       M   E   S   S   A   G   E
0000460        E   2 034   0   1   5  \f 034   0   1   8  \f 034   0   2
$

以下は、データの文字頻度分析です。

  =   3:      1
  =  10:      1
  =  12:    648
  =  14:    883
  =  15:   3461
  =  27:   1384
  =  28:    722
  =  32:  15248
! =  33:    178
" =  34:   1236
# =  35:   1847
$ =  36:      2
% =  37:     44
& =  38:    945
' =  39:    197
( =  40:   2096
) =  41:   1434
* =  42:    695
+ =  43:     25
, =  44:    446
- =  45:   1431
. =  46:     92
/ =  47:     29
0 =  48:   2453
1 =  49:   1279
2 =  50:   1052
3 =  51:    758
4 =  52:    427
5 =  53:    565
6 =  54:    299
7 =  55:    862
8 =  56:    414
9 =  57:    423
: =  58:     78
; =  59:    330
< =  60:      3
= =  61:    313
> =  62:   1683
? =  63:     60
@ =  64:   3472
A =  65:   2268
B =  66:    791
C =  67:   2034
D =  68:   1480
E =  69:   2862
F =  70:    732
G =  71:    692
H =  72:    799
I =  73:   1202
J =  74:    360
K =  75:    358
L =  76:    963
M =  77:    823
N =  78:   1483
O =  79:   1726
P =  80:    588
Q =  81:    507
R =  82:   1411
S =  83:   1624
T =  84:   1905
U =  85:   1172
V =  86:    151
W =  87:    372
X =  88:   1063
Y =  89:    647
Z =  90:    758
[ =  91:   1026
\ =  92:    665
] =  93:    275
^ =  94:    397
_ =  95:   1179
a =  97:      1
c =  99:      1
d = 100:      1
m = 109:    240
o = 111:      2
p = 112:      2
q = 113:      4
r = 114:      2
s = 115:      2
t = 116:      4
u = 117:      1
w = 119:      1
y = 121:      1
z = 122:     15

最後の列の数字の合計は80106と一致しますwc

ご覧のとおり、改行文字(コード10)は1つだけで、ファイルの末尾に表示されます。小文字は少なく、大文字は多く、バックスラッシュも適度ですが(今まで表示されたデータでは見えないもの)、バックスラッシュの後に数字はありません。 ASCII範囲外の文字コードはなく(上位ビットが設定されている文字コードはありません)、ASCII範囲の適用範囲は不完全です。

バックスラッシュの後にどの文字が出てくるのかを確認するために高速パーサーを作成しました。

#include <stdio.h>

int main(void)
{
    int c;
    int count[256] = { 0 };
    while ((c = getchar()) != EOF)
    {
        if (c == '\\')
        {
            c = getchar();
            count[c]++;
        }
    }

    for (int i = 0; i < 255; i++)
    {
        if (count[i] != 0)
            printf("%3d = %5d\n", i, count[i]);
    }

    return 0;
}

このファイルを実行すると、次のようになります。

 12 =     3
 14 =    58
 15 =     3
 27 =    25
 34 =    10
 35 =    51
 37 =    14
 38 =   126
 40 =     9
 44 =    51
 45 =    26
 47 =     2
 59 =    17
 62 =   118
 64 =    46
 65 =     2
 66 =     2
 67 =    17
 69 =     1
 71 =     4
 72 =     5
 74 =    15
 79 =     1
 81 =     9
 83 =     1
 85 =     5
 88 =    18
 90 =    12
 91 =     6
 95 =     8

数の合計は665で、元の文字分析のバックスラッシュ数と一致します。

数値コードは48..57です。バックスラッシュの後の文字は数字ではありません。

これが提示されたさまざまなソリューションが失敗した理由です。データが説明されたものと似ていなかったので、彼らは決して機会を得ませんでした。

答え2

sedを使用してください:

$ cat file
\001abd \002pqr \003xyz
$ sed -E 's/(.)(\\[[:digit:]]{3})/\1\n\2/g' file
\001abd 
\002pqr 
\003xyz

同じsedコマンドを使用しているがデータが異なる例:

$ cat file2
CHANGE^\039^OE@ MORE^\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020
$ sed -E 's/(.)(\\[[:digit:]]{3})/\1\n\2/g' file2
CHANGE^
\039^OE@ MORE^
\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^
\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020

アップデート:FS-番号-番号-番号分割

ASCII「ファイル区切り文字」(FS)文字は16進数です1C。 GNU sedの使用:

sed -E 's/(.)(\x1c[[:digit:]]{3})/\1\n\2/g'

これを実証するためにテストファイルを作成しましょう。

$ echo $'One\x1c123Two\x1c456Three\x1c7none' >newfile

それでは、以下を実行してみましょうsed

$ sed -E 's/(.)(\x1c[[:digit:]]{3})/\1\n\2/g' newfile
One
123Two
456Three7none

回線が正常に分割されました。

議論する

私の端末では、上記のようにFS文字は表示されません。あまり走らないと目立つようになります。たとえば、実行less newfile結果は次のようになります。

One^\123Two^\456Three^\7none

ここでは、FS文字がで表示されることがわかります^\。これは質問に示された第2の入力例と一致する。

CHANGE^\039^OE@ MORE^\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020

答え3

次から始めたい場合:

\001abc \002jkl \003xyz

...到着...

\001abc
\002jkl
\003xyz

...最も簡単で効率的なソリューションは次のとおりです。

tr \  \\n <in >out

\nただし、これはスキーマに基づいて入力をewlineに分割することとは異なり、\[0-9][0-9][0-9]次の影響を受ける可能性があります。

sed 's/\\[0-9]\{3\}/&\n/g' <in >out

...そして次に続くことができます...

\001
abc \002
jkl \003
xyz

\n...おそらく改行文字を挿入したいという意味のようですが今後毎回表示される\[0-9][0-9][0-9]場合は、次のようにできます。

sed 's/\\[0-9]\{3\}/\n&/g' <in >out

...得るために...

\001abc
\002jkl
\003xyz

...各行の末尾にスペースがあります。

ただし、どちらの方法も非常に長い入力ラインを処理するときに問題がある可能性があります。入力ファイル全体に1行しかない場合は、次のことを確実に実行できます。

{   tr '\\' \\n | 
    sed -e:t \
        -e'$!N;/\n[0-9]\{3\}/!s/\n/\\/;tt' \
        -e's/\n/&\\/;P;D'
}   <infile >outfile

上記のコマンドチェーンtrが解析されます。みんな入力のバックスラッシュは改行\n文字であり、結果は結果としてパイプされ、各入力行の最初の3桁をsed再帰的に推定します。長い入力行の処理にはまったく問題がなく、操作が完了したら、出力に少なくとも必要な数のewline文字を含める必要があります。 ewline 文字が次のような場合ttr\n\nいいえその後には3桁の数字が続き、単にバックスラッシュに置き換えられます。そうでない場合はい\n次に、改行文字と3桁の数字の間にバックスラッシュを挿入します。

2番目の例の結果は次のとおりです。


CHANGE^
\039^OE@ MORE^
\040^L^[[00m^OAC DEPOSIT TO WHICH ACCOUNT^N020^^
\055^L^[(1^[[00m^OAA PAYMENT FROM WHICH ACCOUNT^N020

関連情報