패턴에 따라 "한 줄의 텍스트"를 분할하는 방법은 무엇입니까? [폐쇄]

패턴에 따라 "한 줄의 텍스트"를 분할하는 방법은 무엇입니까? [폐쇄]

그래픽이 아닌 문자가 포함된 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

한 줄의 파일 크기는 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-Backslash( Control-A코드 1이 있지만 A코드 65 = 64 + 1이 있고 백슬래시에는 \코드 92 = 64 + 28이 있기 때문).언제나 학생질문에 혼란이 있습니다.

GNU를 참고하세요sed-rBSD가 수행하는 작업을 수행 하는 데 사용됩니다 -E.sed어떤 종류의 기호도 인식되지 않습니다.

연구배경

파일을 이메일로 보냈습니다. 받은 내용이 정확하다면 필요한 내용에 대한 다른 설명이 필요합니다.

단어 수 출력:

$ 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)는 하나만 있으며 파일 끝에 나타납니다. 소문자는 적고, 대문자는 많고, 백슬래시도 적당히 있지만(지금까지 표시된 데이터에서 볼 수 없는 것) 백슬래시 뒤에 숫자가 없습니다. 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 문자가 로 표시되는 것을 볼 수 있습니다 ^\. 이는 질문에 표시된 두 번째 입력 예와 일치합니다.

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

...각 줄 끝에 공백이 있습니다.

그러나 두 방법 모두 매우 긴 입력 라인을 처리할 때 문제가 있을 수 있습니다. 전체 입력 파일에 한 줄만 있으면 다음을 안정적으로 수행할 수 있습니다.

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

위의 명령 체인이 tr구문 분석 됩니다.모두입력의 백슬래시는 \n줄 바꿈 문자이며 결과는 결과로 파이프되어 각 입력 줄의 처음 세 숫자를 sed재귀적으로 추정합니다. 긴 입력 줄을 처리하는 데 전혀 문제가 없으며, 작업이 완료되면 출력에는 최소한 필요한 만큼의 ewline 문자가 포함되어야 합니다. ewline 문자가 다음 과 같은 경우ttr\n\n아니요그 뒤에는 세 자리 숫자가 오고 간단히 백슬래시로 대체됩니다. 그렇지 않은 경우\n그런 다음 줄 바꿈 문자와 세 자리 숫자 사이에 백슬래시를 삽입합니다.

두 번째 예제의 결과는 다음과 같습니다.


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

관련 정보