「column -t」に特定の属性を持つ行を無視させる方法は?

「column -t」に特定の属性を持つ行を無視させる方法は?

/etc/fstabcolumn -te私はパイプを通して素晴らしいフォーマットのテーブルを得るのがどれほど良いかと思いました。
しかし、columnもちろん、コメント行とマウントポイント定義は認識されないため、コメントもすべてのスペースで分割され、テーブル列形式で指定されます。

#                                          /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

columnで始まらないフォーマット行だけを作成する方法はありますか#


fstab編集:上記の例が実際にBtrfsに有効であることを明確にする必要があるようです。サブボリュームsubvolとインストールオプションを使用して別々にインストールできますsubvolid
これはまた、最初の列のデバイスがfstab必ずしも一意である必要はないことを意味します。

答え1

私の考えに実用的な解決策は、ファイル全体がcolumn機能するようにし、コメント行の複数のスペースを単純に縮小することです。

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

それ以外の場合は、行に番号を付け、コメント行とコメント以外の行を別々に処理し、それらをすべて貼り付ける以外にこれを行う方法はありません。

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-

答え2

そして:sednl

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

または:sedgrep

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

または、より短く、sed次の使用awk

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

テストファイルの使用:

# /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

出力は次のとおりです

# /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

仕組み:
最後のコマンドは、前のコマンドで生成されたスクリプトファイルを使用し(読み取り)、マウントポイント定義のみを変更しますsed -f - /etc/fstab/etc/fstab空行を含む他の行は変更しません)。f-stdin

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

最初は、nl -ba -nrz -s:すべての行に番号を付けるために使用されます。

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

column -t最初にコメントアウトされた行または空の行を削除し、残りの行からバックスラッシュをすべてエスケープしてから(この特別な場合は不要であることがわかっている)、マウントポイント定義のみを一覧表示するように出力をパイプします。

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

これはさらに処理されます。

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

上記のスクリプトファイルを生成します。
2番目と3番目は似ています(同じ出力を生成します)。

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

または

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

マウントポイント定義のみを一致させ、バックスラッシュ(存在する場合)をエスケープし、行番号とc\実際の行の内容を印刷します(別々の行に)。

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

その後、パイプを介してcolumn -t同じスクリプトファイルを生成します。


他の方法もed同じですが、ファイルを一度だけ読みます。

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

番号付きの行は入力として使用されed、最初のサブコマンドはp最初にコメントアウトされた行または空白行(g)の両方を印刷し、2番目のサブコマンドはdそれを削除してから残りの行を入力()としてwshell(!)コマンドに渡しますcolumn -t。出力全体sortが編集され、cut先行番号が削除されます。

答え3

「レビューを送信する前に削除するのはどうですか?」という提案がcolumnまったく価値がないわけではありません。

#!/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各行には番号が付けられています。%6d\tつまり、数字の前にスペースがあり、その後にタブ文字が続きます。先行スペースを削除し、タブ文字をスペースに置き換えて出力sed "s/^ *//; s/\t/ /"に似ています。コマンドcolumnは、コメント化された行とコメント化されていない行にgrep分けられます。 (方法file0file1file2XX*X0個以上のXs、つまり1つ以上のXsが続きます。これは「貧しい人々のバージョン」ですX+。つまり、1つ以上のsを移植可能/一般的な方法で表現する方法ですX。 )各ファ​​イルは行番号を保持します元のファイル/etc/fstabから

(cat file1; column -t file2)コメント化されていない行を実行して、column –t結果をコメント化された行(水平間隔は変更されません)にリンクします。次に、sort –n行を元の順序に復元し、sed "s/^[0-9][0-9]* *//"行番号を削除します。

出力:

# /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

これは、空白行と空白を含むコメント行(つまり、タブまたは2つ以上の空白を含む文字列)をサポートしますが、インデントされた行(たとえば、リーダータブまたはスペース)。

このスクリプトを少し強化したい場合(つまり、本番バージョンに似ている)、次のことができます。

  • 一時ファイルを/tmp任意にmktemp生成された名前のファイルに置き換えます。
  • 完了したら、一時ファイルを削除します。
  • 適切な場合は使用するように変更してください[0-9]+(システムが古すぎる場合(たとえば、Solaris、AIX、またはGNUツールのないシステムなど)には適用されない可能性があります)。
  • file1and を削除file2し、最後の行を次のように圧縮します。

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

    しかし、いくつかの行を書いて、より明確に書くのが良いようです。

  • インデントされた行のサポートを追加します。

答え4

列だけではこれを行うことはできないようです。これを行うための簡単なスクリプトを書くことはそれほど難しくありません。

編集:これはうまくいくかもしれませんし、少し短いかもしれません。列を通過しましたが、上記の元の例で試しました。私はこれが空の行を削除することがわかったので、それが問題であれば、まだ少しトリミングする必要があるかもしれません。

#!/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[@]}

ここに元の答えを残しますが、@scottが指摘したように、いくつかの有効なfstabでは機能しません。

#!/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

関連情報