Como fazer com que 'column -t' ignore linhas com características específicas?

5

Eu apenas pensei em como seria interessante canalizar meu /etc/fstab a column -te para obter uma tabela bem formatada.
Mas column obviamente não tem como discernir linhas de comentários e definições de ponto de montagem, então os comentários também são divididos em cada espaço em branco e formatados em colunas de tabelas:

#                                          /etc/fstab:                  static   file                                      system     information.
#
#                                          Use                          'blkid'  to                                        print      the           universally   unique      identifier  for       a
#                                          device;                      this     may                                       be         used          with          UUID=       as          a         more  robust     way  to  name  devices
#                                          that                         works    even                                      if         disks         are           added       and         removed.  See   fstab(5).
#
#                                          <file                        system>  <mount                                    point>     <type>        <options>     <dump>      <pass>

#                                          /                            was      on                                        /dev/sda2  during        installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /                            btrfs    defaults,subvol=@rootfs,metadata_ratio=6  0          1
#                                          /home                        was      on                                        /dev/sda2  during        installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home                        btrfs    defaults,subvol=@home                     0          2

Existe uma maneira de fazer com que column apenas formatem linhas que não iniciam com # ?

Editar: parece que preciso esclarecer que o exemplo acima é de fato um fstab válido. O Btrfs tem subvolumes que podem ser montados separadamente com as opções subvol e subvolid mount.
Isso também significa que os dispositivos na primeira coluna do fstab não são necessariamente únicos.

    
por n.st 26.06.2015 / 19:26

5 respostas

8

Acho que a solução pragmática será deixar column fazer sua parte em todo o arquivo e, em seguida, simplesmente recolher todos os espaços nas linhas de comentário

column -t /etc/fstab | sed '/^#/ s/ \{1,\}/ /g'

Caso contrário, não vejo como fazer isso além de numerar as linhas, processar as linhas de comentário e de não comentários separadamente e, depois, juntá-las novamente, por exemplo,

sort -nk1,1 \
<(nl -nln /etc/fstab | grep -vE '^[[:digit:]]+[[:space:]]+#'| column -t | sed 's/ \{1,\}/\t/') \
<(nl -nln /etc/fstab | grep -E '^[[:digit:]]+[[:space:]]+#') \
| cut -f2-
    
por 26.06.2015 / 22:19
4

Com sed e nl :

nl -ba -nrz -s: /etc/fstab | \
sed '/^[[:digit:]]*:[[:blank:]]*\(#\|$\)/d;//!{s/\/&&/g}' | \
column -t | sed 's|^0*\([[:digit:]]*\):\(.\)|c\\
|' | sed -f - /etc/fstab

ou com sed e grep :

grep -nvE '^[[:blank:]]*(#|$)' /etc/fstab | \
sed -E 's/\/&&/g;s/^([[:digit:]])*:(.*)/c\\
/' | column -t | sed -f - /etc/fstab

ou menor, com sed e awk :

awk '!/^[[:blank:]]*(#|$)/{print NR"c\";gsub(/\/,"&&");print}' \
/etc/fstab | column -t | sed -f - /etc/fstab

Com um arquivo de teste:

# /etc/fstab: static file system information
# <file system> <dir>   <type>  <options>   <dump>  <pass>

LABEL=ROOT    / ext4 noatime,discard 0 1
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  / btrfs  defaults,subvol=@rootfs,metadata_ratio=6 0  1
# /home was on /dev/sda2  during installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home btrfs  defaults,subvol=@home  0 2
LABEL=SWAP   none  swap sw,discard  0 0
UUID=7fa3-cb08  /media ext4 defaults 0 0

a saída é:

# /etc/fstab: static file system information
# <file system> <dir>   <type>  <options>   <dump>  <pass>

LABEL=ROOT                                 /       ext4   noatime,discard                           0  1
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /       btrfs  defaults,subvol=@rootfs,metadata_ratio=6  0  1
# /home was on /dev/sda2  during installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home   btrfs  defaults,subvol=@home                     0  2
LABEL=SWAP                                 none    swap   sw,discard                                0  0
UUID=7fa3-cb08                             /media  ext4   defaults                                  0  0

Como funcionam:
O último sed -f - /etc/fstab modifica apenas as definições de pontos de montagem em /etc/fstab (deixando as outras linhas - incluindo as vazias - inalteradas) usando um script- f ile ( - lido de stdin ) produzido pelo anterior comandos:

4c\
LABEL=ROOT                                 /       ext4   noatime,discard                           0  1
5c\
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /       btrfs  defaults,subvol=@rootfs,metadata_ratio=6  0  1
7c\
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home   btrfs  defaults,subvol=@home                     0  2
8c\
LABEL=SWAP                                 none    swap   sw,discard                                0  0
9c\
UUID=7fa3-cb08                             /media  ext4   defaults                                  0  0

O primeiro usa nl -ba -nrz -s: para numerar todas as linhas e depois

sed '/^[[:digit:]]*:[[:blank:]]*\(#\|$\)/d;//!{s/\/&&/g}'

exclui linhas que foram originalmente comentadas ou vazias e escapa quaisquer barras invertidas nas linhas restantes (não necessário neste caso específico, eu sei) a saída é então canalizada para column -t , então somente as definições de pontos de montagem são colunadas:

000004:LABEL=ROOT                                 /       ext4   noatime,discard                           0  1
000005:UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /       btrfs  defaults,subvol=@rootfs,metadata_ratio=6  0  1
000007:UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home   btrfs  defaults,subvol=@home                     0  2
000008:LABEL=SWAP                                 none    swap   sw,discard                                0  0
000009:UUID=7fa3-cb08                             /media  ext4   defaults                                  0  0

isso é processado posteriormente com

sed 's|^0*\([[:digit:]]*\):\(.\)|c\\
|'

para produzir o arquivo de script mencionado acima.
O segundo e o terceiro são similares (eles produzem a mesma saída), então

grep -nvE '^[[:blank:]]*(#|$)' | sed -E 's/\/&&/g;s/^([[:digit:]])*:(.*)/c\\
/'

ou

awk '!/^[[:blank:]]*(#|$)/{print NR"c\";gsub(/\/,"&&");print}'

irá corresponder apenas às definições de pontos de montagem, escape das barras invertidas (se houver), imprima o número da linha seguido por c\ e (em uma linha separada) o conteúdo real da linha:

4c\
LABEL=ROOT    / ext4 noatime,discard 0 1
5c\
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  / btrfs  defaults,subvol=@rootfs,metadata_ratio=6 0  1
7c\
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home btrfs  defaults,subvol=@home  0 2
8c\
LABEL=SWAP   none  swap sw,discard  0 0
9c\
UUID=7fa3-cb08  /media ext4 defaults 0 0

que é então canalizado para column -t para produzir o mesmo arquivo de script.

Outra forma com ed faz o mesmo, mas lê o arquivo apenas uma vez:

ed -s <<IN <(nl -ba -nrz -s: /etc/fstab) | sort -t: -k1,1 | cut -d: -f2-
g/^[[:digit:]]*:[[:blank:]]*\(#\|$\)/p
g//d
,w !column -t
q
IN

As linhas numeradas são usadas como entrada para ed , o primeiro subcomando p rints de todas as linhas ( g ) que foram originalmente comentadas ou vazias, a segunda d as elimina e então a segunda as linhas restantes são passadas como entrada ( w ) para o comando shell ( ! ) column -t . A saída inteira é sort ed e cut remove os números iniciais.

    
por 26.06.2015 / 23:05
3

A sugestão "Que tal apenas remover comentários antes de alimentar a column ?" não é totalmente sem mérito.

#!/bin/sh
nl -ba /etc/fstab | sed "s/^ *//; s/\t/ /" > file0
grep    "^[0-9][0-9]* #" file0 > file1
grep -v "^[0-9][0-9]* #" file0 > file2
(cat file1; column -t file2) | sort -n | sed "s/^[0-9][0-9]* *//"

nl –ba numera cada linha; o formato é, efetivamente, %6d\t ; ou seja, um número com espaços iniciais seguidos por uma tabulação. sed "s/^ *//; s/\t/ /" retira os espaços principais e substitui a guia por um espaço, fazendo com que pareça mais com o que column output parece. Os comandos grep quebram file0 em file1 , as linhas com comentários, e file2 , as linhas sem comentários. (%código% significa XX* seguido por zero ou mais X s; em outras palavras; um ou mais X s. Esta é a versão do "pobre homem" de X ; ou seja, uma maneira de dizer um ou mais X+ s de maneira portátil / universal.) Cada arquivo retém os números de linha do arquivo X original .

/etc/fstab executa as linhas que não são de comentários por meio de (cat file1; column -t file2) , concatenando o resultado para as linhas comentadas (cujo espaçamento horizontal não é modificado). Então, column –t coloca as linhas de volta na ordem original, e sort –n retira os números de linha.

Saída:

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>

# / was on /dev/sda2 during installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /      btrfs  defaults,subvol=@rootfs,metadata_ratio=6  0  1
# /home was on /dev/sda2 during installation
UUID=8fa99d69-8dac-4aca-bb61-90f753ba5169  /home  btrfs  defaults,subvol=@home                     0  2

Observe que isso oferece suporte a linhas em branco e linhas de comentários com espaço em branco incorporado (ou seja, guias incorporadas ou seqüências de caracteres de dois ou mais espaços), mas não linhas recuadas (por exemplo, guias ou espaços ).

Se você quiser endurecer este script um pouco (ou seja, torná-lo mais de uma versão de produção), você poderia

  • Substitua os arquivos temporários por arquivos sed "s/^[0-9][0-9]* *//" com nomes gerados aleatoriamente ( /tmp ).
  • Exclua os arquivos temporários após a conclusão.
  • Alterar para usar mktemp quando apropriado (isso pode não ser aplicável a você se você tiver um sistema muito antigo; por exemplo, Solaris, AIX ou qualquer coisa sem as ferramentas GNU).
  • Dispense com [0-9]+ e file1 e comprima a última linha para algo como

    (grep "^[0-9][0-9]* #" file0; grep -v "^[0-9][0-9]* #" file0 | column -t) | …
    

    Mas acredito que é melhor usar algumas linhas extras e ser mais claro.

  • Adicione suporte para linhas recuadas.
por 26.06.2015 / 22:25
0

Eu não acho que você pode fazer isso sozinho com colunas. escrever um roteiro trivial para fazer isso não é muito difícil.

Edit: Isso pode funcionar e é um pouco menor. Eu tentei no exemplo original acima, embora já tenha sido colocado através da coluna. Eu notei que isso removerá as linhas vazias, então, se isso for uma preocupação, talvez ainda seja necessário algum polimento.

#!/bin/bash

INPUTFILE="${1}"

IFS=$'\r\n' GLOBIGNORE='*';
COMMENTS=('grep -n ^# "${INPUTFILE}"') 
ENTRIES=('grep -n -v ^# "${INPUTFILE}" | column -t')
TMPTAB=('printf "%s\n" ${ENTRIES[@]} && printf "%s\n" ${COMMENTS[@]}')

NEWTAB=('printf "%s\n" ${TMPTAB[@]} | sort -n -t: -k1 | sed 's/^[0-9]\+://'')
printf "%s\n" ${NEWTAB[@]}

Vou deixar minha resposta original aqui, mas como @scott apontou, não funciona para alguns fstabs válidos.

#!/bin/bash 

# columnize the non-comment lines
TABS='grep -v ^# /etc/fstab | column -te'

# read the original fstab
while read LINE
 do 
  echo "${LINE}" | grep ^# > /dev/null 

  # if it is a comment line just write it in
  if [ $? -eq 0 ]
  then
       echo "${LINE}" >> new.fstab
  else
    # otherwise get the matching entry from the columnized fstab 
    ENTRY='echo "${LINE}" | awk '{ print $1 }''
    echo "${TABS}" | grep ^"${ENTRY}" >> new.fstab
  fi
 done < /etc/fstab
    
por 27.06.2015 / 01:30
-2

Como sugerido, abandonar os comentários?

grep -v "^#" /etc/fstab | column -te
    
por 26.06.2015 / 19:49