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
Isso fornece a saída necessária:
Saída do seu exemplo
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ênciaA 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 comoabc123
, o.*
consumiráabc12
, deixando[0-9]+
para corresponder apenas3
. Você precisaria de um " não dígito " para restringir a primeira correspondência:([^0-9]*)([0-9]+)
para obterabc
e123
.O comando de substituição aqui é combinar e remover
NNN-NNN
ondeNNN
está uma série de três dígitos.Para corresponder pelo menos um dígito, use
1,
no lugar de3
:Isso corresponde ao uso
+
em uma expressão regular estendida. As expressões regulares usadas porsed
padrão são expressões regulares "básicas" e+
corresponderiam a um caractere de adição literal. A maioriased
das implementações também suporta expressões estendidas com-E
:Usar
*
, como em[0-9]*-[0-9]*
, não funcionaria, pois corresponderia ao traçostr-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:
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 no último sublinhado, não necessariamente após os dígitos que você deseja remover se houver vários sublinhados em aquela 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.