Eu posso fazer assim:
sed 's|\(,[^,]*,\)\{0,1\}\([^,]\{1,2\}\)|/|g
' <<\IN
hello_hello,123-world567-helloworld123456,world1234-hello09876
IN
... que imprime ...
/he/ll/o_/he/ll/o,123-world567-helloworld123456,/wo/rl/d1/23/4-/he/ll/o0/98/76
Então, mais das alterações feitas são feitas na segunda s///
ubstitution - mas isso é porque eu removi todas as primeiras.
Portanto, a maior parte do seu problema foi que você estava simplesmente dizendo sed
para substituir em /
após cada dois caracteres - o .
dots significa qualquer char e o g
significa global - ou todos .
A segunda maior parte foi que a primeira substituição não estava ajudando você - e foi completamente desnecessária.
Mais do que isso, você também estava inserindo uma vírgula extra na primeira substituição - então, depois que eu consegui acertar o primeiro bit, eu ainda estava correndo em campos extras. Olhe:
\(,[^,]*,\)\{0,1\}\([^,]\{1,2\}\)|/
Essa é a declaração de substituição que funcionou para mim e é por isso:
-
\(,[^,]*,\)\{0,1\}
- em um contexto global, você tem que ter cuidado para obter apenas o quanto precisar. Você estava substituindo cada dois caracteres e é isso que você tem -sed
é ganancioso . Isso é referenciado primeiro - o que é importante - porque comosed
lê da esquerda para a direita, ele normalmente apenas insere uma barra entre cada dois caracteres sequenciais e não de vírgula, mas se encontrar uma vírgula, ela será lida até a próxima. e salve o bloco inteiro emsem inserir nenhuma barra.
-
\([^,]\{1,2\}\)
- Você não pode usar os.
dots aqui - eles corresponderão a uma vírgula e você acabará escrevendo nas barras depois de pular um delimitador. Você precisa excluir explicitamente as vírgulas. E é isso que isso faz - cada sequência de 1 ou 2 delas -, emborased
sempre traga o maior desses números possíveis.
Uma diferença que eu posso ver entre isso e aquilo em seu exemplo é que a primeira barra aqui está na cabeça da string e não há barra final, enquanto a sua faz o oposto. Para remediar isso, conforme necessário:
...;s|^/\(.*/.\)/*$|/|...