Houve uma declaração inicial do problema e várias soluções foram propostas. Acontece que eles não funcionaram porque os dados reais não correspondiam à descrição.
Resposta viável
My pattern is:
FS[0-9][0-9][0-9]
, (FS is 'field separator'); how use that in thesed
script?
Com Bash e BSD sed
, você pode usar isso (que é estreitamente baseado no que John1024 < um href="https://unix.stackexchange.com/a/235176/"> proposto e usa o BSD e o Mac OS X sed
notação -E
para ativar expressões regulares estendidas):
sed -E $'s/(.)(\x1C[[:digit:]]{3})/\1\\n\2/g' file1
A notação $'…'
é o mecanismo ANSI C do Bash. O FS possui valor de byte 28, hex 0x1C ou octal 038. As barras duplas invertidas representam uma barra invertida vista por sed
; o \n
precedido por \
satisfaz o manual sed
que diz (na seção s///
):
A line can be split by substituting a newline character into it. To specify a newline character in the replacement string, precede it with a backslash.
Verifique o que funciona com o GNU sed
.
Eu também observo que FS é algumas vezes codificado como Control-Backslash (porque Control-A possui código 1, mas A possui código 65 = 64 + 1; barra invertida \ possui código 92 = 64 + 28); isso provavelmente é responsável pela confusão do alwaystudent na questão.
Note que o GNU sed
usa -r
para fazer o que o BSD faz com% código%; POSIX -E
não reconhece a notação.
Histórico de investigação
Recebi o arquivo por e-mail, e se o que recebi for preciso, precisamos de uma caracterização diferente do que é necessário.
Saída de contagem de palavras:
$ wc file1
1 8804 80106 file1
$
Aqui está a saída de um dump hexadecimal:
$ 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
$
Aqui estão os mesmos dados de sed
:
$ 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
$
E aqui está uma análise de frequência de caracteres dos dados:
= 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
A soma dos números na última coluna é 80106, que concorda com od -c
.
Como você pode ver, há apenas uma nova linha (código 10) e aparece no final do arquivo. Há muito poucas letras minúsculas, muitas letras maiúsculas, um número moderado de barras invertidas, mas (o que você não pode ver pelos dados mostrados até agora é isso) nenhuma das barras invertidas é seguida por um dígito. Observe que não há códigos de caracteres fora do intervalo ASCII (nenhum com o bit alto definido) e a cobertura do intervalo ASCII também não está completa.
Eu escrevi um programa de análise rápida para ver quais caracteres seguem uma barra invertida:
#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;
}
Quando executado no arquivo, é produzido:
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
A soma das contagens é de 665, o que concorda com o número de barras invertidas na análise original do personagem.
Os dígitos têm códigos 48..57; nenhum dos caracteres depois de uma barra invertida é um dígito.
É por isso que as várias soluções mostradas falham - elas nunca tiveram uma chance, porque os dados nem sequer começam a se parecer com o que é descrito.