Desejo gerar um arquivo csv para informar quais servidores possuem arquivos e propriedade específicos. Aqui está a saída original que obtive:
server01,server02,server03,owner,/etc/file1
server04,owner,/etc/file2
server05,server06,owner,/etc/file3
Desejo substituir as vírgulas entre os nomes dos servidores pela nova linha do formato do Windows (CF + LR) e adicionar aspas entre eles para que o CSV exiba todos os servidores na mesma caixa.
Saída desejada:
"server01
server02
server03",owner,/etc/file1
"server04",owner,/etc/file2
"server05
server06",owner,/etc/file3
Como alcançá-lo com sed?
Se for tudo o que resta de um literal
,owner,
que você deseja agrupar em um campo:Com GNU
sed
:Com
perl
:Se for tudo, exceto os dois últimos campos:
Com GNU
sed
:Com
perl
:Ou usando o
Text::CSV
módulo perl para fazer a análise e formatação CSV corretamente:Se o arquivo estiver codificado em UTF-16 ou UTF-8 com BOM, o que não é inédito para arquivos da Microsoft, você provavelmente terá que se adaptar (consulte
perldoc Text::CSV
para essa abordagem) ou talvez prefira fazer a reformatação de uma<file dos2unix | ... | unix2dos
maneira para que você possa processar entrada sã.Eu não faria isso com
sed
, eu usariaperl
em vez disso (ou talvezawk
- mas então eu teria que escrever minhas próprias funçõespop()
ejoin()
em vez de usar os perl integrados):Primeiro, ele remove os dois últimos elementos (o proprietário e o nome do arquivo) da
@F
matriz (@F
é criado automaticamente para cada linha de entrada por causa da-a
opção de usar vírgulas como separador de campo conforme especificado pela-F,
opção - semelhante a como o awk divide automaticamente sua entrada) e armazena-os em variáveis$file
e$owner
."\"" . join("\r\n", @F) . "\""
constrói uma string onde cada elemento de @F é separado por caracteres CR+LF e toda a string é colocada entre aspas duplas.Esta string é unida (por vírgulas) com
$owner
e$file
, e impressa.Você deseja combinar o primeiro campo delimitado por vírgula com todos os campos a seguir, até (mas não incluindo) os dois últimos em cada registro, colocando-os entre aspas, produzindo um único campo CSV entre aspas. Em seguida, você deseja substituir as vírgulas incorporadas nesse campo combinado por CR+LF.
Você pode fazer isso facilmente invertendo o conteúdo de cada linha em seu arquivo, inserindo aspas duplas após a segunda vírgula, invertendo a linha novamente e inserindo aspas duplas no início:
Como agora temos um arquivo CSV sem cabeçalho devidamente citado, podemos usar Miller (
mlr
; uma ferramenta específica para trabalhar com dados estruturados, como CSV) para substituir todas as vírgulas no primeiro campo por CR+LF:Observe que não há necessidade de colocar aspas nos campos, pois, em um sistema Unix, os separadores de campo e registro não são incorporados aos campos neste conjunto de dados. Podemos mostrar isso extraindo o segundo campo de cada registro com uma chamada separada para
mlr
:Você deseja manter a citação original da saída do último
sed
comando e, em seguida, usar--quote-original
:Idealmente, porém, você corrigiria qualquer código que produzisse essa saída CSV quebrada para que o campo estivesse correto desde o início, em vez de corrigi-lo em uma etapa de pós-processamento.
Usando apenas Miller:
Isso leria o arquivo como um arquivo de texto simples delimitado por vírgulas e implicitamente indexado. Em seguida, ele anexaria o segundo e os campos posteriores ao final do primeiro campo com CR+LF como delimitador, excluindo cada campo anexado até restar apenas três campos. Em seguida, cita explicitamente o primeiro campo.