AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 788007
Accepted
Christopher Karsten
Christopher Karsten
Asked: 2024-12-12 18:47:23 +0800 CST2024-12-12 18:47:23 +0800 CST 2024-12-12 18:47:23 +0800 CST

Converter dados de colunas delimitadas por barras verticais em formato de tabela HTML para e-mail

  • 772

Estou tentando converter o formato de dados delimitado para saída de tabela de colunas HTML para impressão por e-mail e não tenho certeza de como usar o delimitador de barra vertical como separador para formatação tabular HTML.

Abaixo está o que eu poderia usar se um espaço fosse um separador, mas neste exemplo estou usando um pipeline (|).

awk ' BEGIN {
print "To: '[email protected]'"
#print "MIME-Version: 1.0"
print "Content-Type: text/html"
print "Subject: This is a test email"
print "<html><body><table border=1 cellspacing=0 cellpadding=3>"
print "<tr>"
print "<td>SID</td>";
print "<td>PID</td>";
print "<td>Username</td>";
print "<td>Database</td>";
print "<td>Hostname</td>";
print "<td>Program</td>";
print "<td>Connected</td>";
print "<td>Idle Time</td>";
print "<td>Query Time</td>";
print "<td>EST COST</td>";
print "<td>SEQ SCAN</td>";
print "<td>Query</td>";
print "</tr>"
} {
print "<tr>"
print "<td>"$1"</td>";
print "<td>"$2"</td>";
print "<td>"$3"</td>";
print "<td>"$4"</td>";
print "<td>"$5"</td>";
print "<td>"$6"</td>";
print "<td>"$7"</td>";
print "<td>"$8"</td>";
print "<td>"$9"</td>";
print "<td>"$10"</td>";
print "<td>"$11"</td>";
print "<td>"$12"</td>";
print "</tr>"
} END {
print "</table></body></html>"
} ' /home/test/test.unl | sendmail -t

Dentro do arquivo test.unl está o seguinte:

15422216|-1|dwhvo|test|pd244zax.test.corp|N/A|    10:56:53|    -0:00:30|10:57:22|1045127|1|SELECT sba_sub_aux.sba_subscriber_id, sba_sub_aux.sba_id_number, sba_sub_aux.sba_matchcode, sba_sub_aux.sba_marketing, sba_su|

Gostaria de obter o seguinte em formato de tabela por e-mail.

insira a descrição da imagem aqui

awk
  • 4 4 respostas
  • 447 Views

4 respostas

  • Voted
  1. Stéphane Chazelas
    2024-12-12T19:56:20+08:002024-12-12T19:56:20+08:00

    Se você remover o final |e adicionar um cabeçalho:

    SID|PID|Username|Database|Hostname|Program|Connected|Idle Time|Query Time|EST COST|SEQ SCAN|Query
    

    Então, isso se torna um TSV simples com pipe como delimitador, e você pode usar, por exemplo, mlrpara converter para um CSV adequado, que pandocpode ser convertido para HTML:

    {
      echo 'SID|PID|Username|Database|Hostname|Program|Connected|Idle Time|Query Time|EST COST|SEQ SCAN|Query'
      sed 's/|$//' your-file
    } |
      mlr --itsvlite --ifs pipe --ocsv cat |
      pandoc -s -f csv -t html -M 'pagetitle=My table' \
        -V 'header-includes=<style>table,th,td{border:1px solid;border-collapse:collapse}</style>' > result.html
    

    Isso cuidará do escape adequado do HTML no conteúdo das células.

    Para alinhar à direita algumas colunas, como na saída esperada, outra opção é usar markdown como formato intermediário.

    {
     echo 'SID|PID|Username|Database|Hostname|Program|Connected|Idle Time|Query Time|EST COST|SEQ SCAN|Query'
     sed 's/|$//' your-file
    } |
      mlr --itsvlite --ifs pipe --omd cat |
      perl -pe 's{-+}{substr("110000101110",$n++,1)?"$&:":":$&"}ge if $. == 2' |
      pandoc -s -f markdown -t html -M 'pagetitle=My table' \
        -V 'header-includes=<style>table,th,td{border:1px solid;border-collapse:collapse}</style>' > result.html
    

    Acima, use perlpara especificar o alinhamento de cada coluna com base no 110000101110"mapa de bits" (1 para direita, 0 para esquerda).

    Cuidado mlrpara não escapar dos operadores de sintaxe markdown nas células da tabela. Então, por exemplo, se você tiver `foo`ou **bar**em algumas das células, elas serão convertidas por pandocpara o equivalente HTML ( <code>foo</code>, <strong>bar</strong>).

    Se pandocfor difícil instalar no seu sistema, você pode fazer tudo em perl(que deve ser pré-instalado), e os módulos HTML::Tablee HTML::Entitiesque, se ainda não estiverem instalados, devem ser fáceis de instalar, mesmo que não estejam empacotados no seu sistema (como usando cpan):

    perl -MHTML::Table -MHTML::Entities -C -F'\|' -lane '
      BEGIN {
        $t = new HTML::Table(
          -border  => 1,
          -spacing => 0,
          -padding => 0,
          -head    => ["SID","PID","Username","Database","Hostname","Program","Connected","Idle Time","Query Time","EST COST","SEQ SCAN","Query"]
        );
      }
      $t->addRow(map {encode_entities$_} @F);
      END {
        $t->setColAlign(++$i, qw(left right)[$_]) for qw(1 1 0 0 0 0 1 0 1 1 1 0);
        print "<html><body>$t</body></html>";
      }' your-file > result.html
    

    O Perl também possui módulos para formatar e enviar e-mails corretamente.

    • 7
  2. Best Answer
    Fravadona
    2024-12-12T20:00:39+08:002024-12-12T20:00:39+08:00

    Como @GillesQuénot comentou, dividir uma linha |com awk é tão simples quanto awk -F '|'.

    Dito isso, recomendo que você defina duas funções: uma para escapar do texto HTML (os dados de exemplo que você mostrou não precisam disso, mas nunca se sabe...) e outra para imprimir uma linha inteira da tabela HTML; isso deixará o programa "mais limpo" e robusto.

    awk -F '|' '
        BEGIN {
            # ...
            print "<html><body><table border=1 cellspacing=0 cellpadding=3>"
            $0 = "SID|PID|Username|Database|Hostname|Program|Connected|Idle Time|Query Time|EST COST|SEQ SCAN|Query"
            print_as_tr()
        }
        {
            sub(/.$/, "") # fix the record for it to contain only what you want
            print_as_tr()
        }
        END {
            print "</table></body></html>"
        }
    
        function print_as_tr(    i) {
            print "<tr>"
            for (i = 1; i <= NF; i++)
                print "<td>" html_textify($i) "</td>"
            print "</tr>"
        }
        function html_textify(s) {
            gsub(/&/, "\\&amp;", s)
            gsub(/</, "\\&lt;", s)
            gsub(/>/, "\\&gt;", s)
            return s
        }
    '
    
    • 5
  3. Christopher Karsten
    2024-12-12T19:20:43+08:002024-12-12T19:20:43+08:00

    awk -F '|'funciona para mim.

    awk -F '|' ' BEGIN {
    print "To: '[email protected]'"
    #print "MIME-Version: 1.0"
    print "Content-Type: text/html"
    print "Subject: This is a test email"
    print "<html><body><table border=1 cellspacing=0 cellpadding=3>"
    print "<tr>"
    print "<td>SID</td>";
    print "<td>PID</td>";
    print "<td>Username</td>";
    print "<td>Database</td>";
    print "<td>Hostname</td>";
    print "<td>Program</td>";
    print "<td>Connected</td>";
    print "<td>Idle Time</td>";
    print "<td>Query Time</td>";
    print "<td>EST COST</td>";
    print "<td>SEQ SCAN</td>";
    print "<td>Query</td>";
    print "</tr>"
    } {
    print "<tr>"
    print "<td>"$1"</td>";
    print "<td>"$2"</td>";
    print "<td>"$3"</td>";
    print "<td>"$4"</td>";
    print "<td>"$5"</td>";
    print "<td>"$6"</td>";
    print "<td>"$7"</td>";
    print "<td>"$8"</td>";
    print "<td>"$9"</td>";
    print "<td>"$10"</td>";
    print "<td>"$11"</td>";
    print "<td>"$12"</td>";
    print "</tr>"
    } END {
    print "</table></body></html>"
    } ' /home/test/test.unl | sendmail -t
    

    Saída exibida como eu queria no e-mail.

    • 4
  4. Ed Morton
    2024-12-14T20:32:49+08:002024-12-14T20:32:49+08:00

    A resposta de @Fravadona é boa, aqui vai apenas uma abordagem alternativa, usando qualquer awk POSIX, para considerar que, na minha opinião, não é significativamente melhor, além de algumas diferenças cosméticas/sinos e assobios. Ela basicamente isola cada parte específica da saída, fornecendo uma função separada para cada nível/segmento de HTML, o que pode torná-la um pouco mais fácil e menos propensa a erros para modificar, se necessário, no futuro:

    $ cat tst.sh
    #!/usr/bin/env bash
    
    awk '
    
        BEGIN {
            FS = "[|]"
            Indent = -2
            prt_html()
            exit
        }
    
        function prt_html() {
            prt_beg("<html>")
            prt_body()
            prt_end("</html>")
        }
    
        function prt_body() {
            prt_beg("<body>")
            prt_table()
            prt_end("</body>")
        }
    
        function prt_table() {
            prt_beg("<table border=1 cellspacing=0 cellpadding=3>")
            numHdrCells = prt_hdr_row("SID|PID|Username|Database|Hostname|Program|Connected|Idle Time|Query Time|EST COST|SEQ SCAN|Query")
            prt_data_rows(numHdrCells)
            prt_end("</table>")
        }
    
        function prt_data_rows(numHdrCells, line) {
            while ( (getline line) > 0 ) {
                prt_data_row(numHdrCells,line)
            }
        }
    
        function prt_hdr_row(s,     numCells) {
            prt_beg("<tr>")
            numCells = prt_hdr_cells(s)
            prt_end("</tr>")
            return numCells
        }
    
        function prt_data_row(numHdrCells,s) {
            prt_beg("<tr>")
            prt_data_cells(numHdrCells,s)
            prt_end("</tr>")
        }
    
        function prt_hdr_cells(s,    numCells,f,i) {
            numCells = split(s, f)
            for (i = 1; i <= numCells; i++) {
                prt_cell("th",f[i])
            }
            return numCells
        }
    
        function prt_data_cells(numHdrCells,s,    f,i) {
            split(s, f)
            # Force the number of cells printed for each data row
            # to match the number of cells printed for the header.
            for (i = 1; i <= numHdrCells; i++) {
                prt_cell("td",f[i])
            }
        }
    
        function prt_cell(cellType,s) {
            Indent += 2
            # Strip any leading/trailing white space around this cell
            gsub(/^[[:space:]]+|[[:space:]]+$/, "", s)
            prt_indented("<" cellType ">" escape_html(s) "</" cellType ">")
            Indent -= 2
        }
    
        function escape_html(s) {
            gsub(/&/, "\\&amp;", s)
            gsub(/</, "\\&lt;", s)
            gsub(/>/, "\\&gt;", s)
            return s
        }
    
        function prt_beg(s) { Indent += 2; prt_indented(s) }
        function prt_end(s) { prt_indented(s); Indent -= 2 }
        function prt_indented(s) { printf("%*s%s\n", Indent, "", s) }
    
    ' "${@:--}"
    

    $ ./tst.sh test.unl
    <html>
      <body>
        <table border=1 cellspacing=0 cellpadding=3>
          <tr>
            <th>SID</th>
            <th>PID</th>
            <th>Username</th>
            <th>Database</th>
            <th>Hostname</th>
            <th>Program</th>
            <th>Connected</th>
            <th>Idle Time</th>
            <th>Query Time</th>
            <th>EST COST</th>
            <th>SEQ SCAN</th>
            <th>Query</th>
          </tr>
          <tr>
            <td>15422216</td>
            <td>-1</td>
            <td>dwhvo</td>
            <td>test</td>
            <td>pd244zax.test.corp</td>
            <td>N/A</td>
            <td>10:56:53</td>
            <td>-0:00:30</td>
            <td>10:57:22</td>
            <td>1045127</td>
            <td>1</td>
            <td>SELECT sba_sub_aux.sba_subscriber_id, sba_sub_aux.sba_id_number, sba_sub_aux.sba_matchcode, sba_sub_aux.sba_marketing, sba_su</td>
          </tr>
        </table>
      </body>
    </html>
    
    • 1

relate perguntas

  • remova o número de linhas duplicadas com base na correspondência antes da primeira vírgula

  • anexar linhas após outros arquivos linha por linha

  • Como remover uma única linha entre duas linhas

  • Reorganize as letras e compare duas palavras

  • Embaralhamento de arquivo de várias linhas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve