Ok, então este é realmente um pouco complicado. Indiscutivelmente, o regex não é a melhor ferramenta para o trabalho, mas pode fazê-lo.
-replace "(?<=^((\|[^|]*){5})+)\|","'n|"
Vou tentar orientá-lo:
- Seu texto tem uma seção que você deseja corresponder e uma seção que você deseja substituir . Tradicionalmente, regex substitui toda a string de pesquisa, então você usaria um grupo de captura para especificar alguma parte da string de pesquisa para ser clonado para a saída de substituição. Outra maneira é usar um lookaround , que foi o que fiz aqui. O PowerShell (.NET) é uma das poucas linguagens regex que suporta lookbehinds de comprimento variável , então estamos com sorte.
- A seção
(?<=)é um lookbehind. Isso significa que tudo entre o=e o)é correspondido , mas não substituído . Portanto,^((\|[^|]*){5})+é usado como uma condição - a substituição só acontecerá se esse bit corresponder ao texto antes da substituição pretendida. - A seção
^((\|[^|]*){5})*[^|]*pode ser resumida como "desde o início da linha (^), corresponder conjuntos de cinco|s e depois corresponder ao texto até o próximo|".- O início da linha
^é importante - caso contrário, pode corresponder a qualquer ponto da linha e não há garantia de quantos|s vieram antes. - Como
|tem um significado especial na regex, ele precisa ter escape:\|. Não precisa ser escapado quando estiver dentro de uma classe de caracteres ([]). -
[^|]*significa "texto até o próximo|" - mais tecnicamente, "quantos caracteres forem diferentes de|" - mais tecnicamente "repita a classe de caractere[^|]quantas vezes for possível, onde esse caractere class corresponde a qualquer caractere diferente de|". -
*significa "zero ou mais repetições do caractere anterior, o maior número possível" - Portanto,
(\|[^|]*)significa correspondência|seguido pelo maior número possível de caracteres até o próximo|. Isto irá corresponder a|text -
{5}significa repetir o token anterior exatamente 5 vezes. É exatamente equivalente a copiar e colar o token anterior 5 vezes. Então, isso vai corresponder a|text|text|text|text|text -
((\|[^|]*){5})+é uma ou mais repetições desse grupo inteiro. Por isso, pode corresponder a|text|text|text|text|text,|text|text|text|text|text|text|text|text|text|text, etc. - em múltiplos de 5. A razão pela qual usamos+em vez de*é que não queremos corresponder ao grupo vazio e substituir o primeiro|. - E isso faz todo o lookbehind, o que significa que só substituirá um
|por um múltiplo de 5|s atrás dele, desde o início da linha.
- O início da linha
- Após isso, com um
\|como o texto real a ser substituído, precedido pela aparência correspondente. -
Tomando seu exemplo
|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1|STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2|STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3, ele corresponderá ao seguinte:|STATUS1|HOSTNAME1|IP1|MAC1|IS_WIRED1**|**STATUS2|HOSTNAME2|IP2|MAC2|IS_WIRED2**|**STATUS3|HOSTNAME3|IP3|MAC3|IS_WIRED3
Você notará aqui (se ainda não o fez) que está realmente tentando substituir todos os 5 | menos o primeiro, nem todo 6º . Mas o método lookbehind manipula a situação "menos o primeiro" de forma bastante clara.
E agora a string de substituição.
- Como este é o PowerShell, quando queremos
\n, na verdade queremos'nporque o caractere de escape do PowerShell é'. Note que isto é necessário apenas na string de substituição; na regex em si você ainda usaria\npara passar essa sequência literal para o mecanismo regex. - E como você tem um líder
|em cada linha, precisamos adicionar um novo|após a nova linha. Isso funciona porque suas linhas originais não terminam com|, portanto, não há nada a substituir no final das linhas, portanto, não terminamos com uma nova linha extra nem perdemos|.
Se você preferir o método de grupo de captura mais tradicional:
-replace "((?:[^|]+\|){4}[^|]+)\|","'$1'n|"
Descobrir como isso funciona é deixado como um exercício para o leitor;) Dica: o $1 backreference deve ser escapado (com ' ) porque senão o PowerShell o interpreta como uma variável shell.