
A string original é assim:
str-str001-002_01
str-str005-006_05
Gostaria de extrair a string antes do número e depois do sublinhado, então ficaria assim:
str-str_01
str-str_05
Lembro que o sed poderia separar o padrão em grupos como este:
sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\1\3/p'
mas imprime:
str-str0002_01
Então me lembro que [0-9] é apenas um número, então tentei com o sinal + ou *. Então dá um resultado vazio.
obs: usando
echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]-[0-9]\)\(.*$\)/\2/p'
Posso ver que combina 1-0
.
Então eu tentei com:
echo 'str-str001-002_01' | sed -n 's/\(^.*\)\([0-9]\+-[0-9]\+\)\(.*$\)/\2/p'
deixou os 2 primeiros números e só corresponde
1-002
então como fazer com que combine001-002
Responder1
Isso fornece a saída necessária:
sed -nE 's/^([^0-9]*).*_([^_]+)$/\1_\2/p'
Saída do seu exemplo
str-str_01
str-str_05
Explicação
sed -nE 's/…/…/p'
- Use EREs, não imprima linhas a menos que correspondam^
- âncora no início da linha([^0-9]*)
- corresponder a um padrão tão longo quanto possível, que seja pelo menos um caractere que não seja um dígito.*_
- combine o máximo possível (incluindo nada), seguido por "_
"([^_]+)
- combine o maior padrão possível (pelo menos um caractere) que não seja um sublinhado$
- âncora no final da linha\1_\2
- substitua a linha inteira pela primeira(…)
correspondência, "_
", e pela segunda(…)
correspondência
A razão pela qual suas tentativas não funcionaram como esperado é porque *
(e +
) é ganancioso - consumirá tantos caracteres quanto possível que correspondam ao átomo anterior. Então para um ERE (.*)([0-9]+)
aplicado a algo como abc123
, o .*
consumirá abc12
, deixando [0-9]+
para corresponder apenas 3
. Você precisaria de um "não dígito" para restringir a primeira correspondência: ([^0-9]*)([0-9]+)
para obter abc
e 123
.
Responder2
$ cat file
str-str001-002_01
str-str005-006_05
$ sed 's/[0-9]\{3\}-[0-9]\{3\}//' file
str-str_01
str-str_05
O comando de substituição aqui é combinar e remover NNN-NNN
onde NNN
está uma série de três dígitos.
Para combinarpelo menos umdígito, use 1,
no lugar de 3
:
$ sed 's/[0-9]\{1,\}-[0-9]\{1,\}//' file
str-str_01
str-str_05
Isso corresponde ao uso +
em uma expressão regular estendida. As expressões regulares usadas por sed
padrão são expressões regulares "básicas" e +
corresponderiam a um caractere de adição literal. A maioria sed
das implementações também oferece suporte a expressões estendidas com -E
:
$ sed -E 's/[0-9]+-[0-9]+//' file
str-str_01
str-str_05
Usar *
, como em [0-9]*-[0-9]*
, não funcionaria, pois corresponderia ao traço str-str
(que tem zero dígitos ao seu redor).
Se você sentir que realmente precisa combinar toda a linha e capturar os bits que deseja manter, você também pode fazer isso. O comando a seguir captura os não dígitos iniciais e o bit final, incluindo o sublinhado:
$ sed 's/\([^0-9]*\).*\(_.*\)/\1\2/' file
str-str_01
str-str_05
Isso, no entanto, é IMHO um pouco difícil de decifrar e faz suposições sobre o início e o fim da string que você nunca mencionou na pergunta. O início não pode, por exemplo, conter dígitos antes dos dígitos que você deseja remover, e o final da string será cortado nodurarsublinhado, não necessariamente após os dígitos que você deseja remover se houver vários sublinhados nessa parte da string.
Você sempre pode adicionar mais informações a essa expressão para garantir que apenas o NNN-NNN
bit não seja capturado, mas isso tornaria ainda mais difícil entender a expressão.