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 comosedlê 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 -, emborasedsempre 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|^/\(.*/.\)/*$|/|...