"column -t"などのコマンドは、出力に区切り文字を保持します。

"column -t"などのコマンドは、出力に区切り文字を保持します。

簡単なフォームを編集しています。フォーマットがうまくいってほしいです。tblまたはこれと同様のものを使用することもできますが、latexこれは過度に見えます。プレーンテキストでも十分です。シンプルなので、ソースを出力に入れるのが良いようです。したがって、ソースも見るのが好きです。これは完璧な作業を行う必要があるようですcolumn -s '|' -t。区切り文字を見つけ、各列の最大幅に基づいて並べ替えるスペースを自動的に挿入します。残念ながら、追加の編集後に再実行できないように区切り文字が削除されます。出力が入力として機能するようにすばやくこれを実行できる優れたテキスト処理ツールはありますか?それとも、私は自分で書く必要がありますか?

編集:以下は私が望むものの例です。

foo |   bar | baz
abc def | 12 | 23456

しなければならない

foo     | bar | baz
abc def | 12  | 3456

セパレータとスペーサは' '一緒に使用するとcolumn -t非常に効果的です。しかし、私のアイテムにスペースがあるので使用できません。スペーサーを仕切りと異ならせることは状況を複雑にする。区切り文字の横にある区切り文字として扱うのが役に立つと思いましたが、そうではありませんcolumn -s '|' -t(明らかに現在の動作も便利ですが)。

答え1

あなたの質問が何であるかを正しく理解したかどうかはわかりません。しかし、追加の時間区切り記号を追加すると、この問題は解決されますか?したがって、2 番目の区切り記号を使用して区切り記号を表示し、元の区切り文字を変更せずに残すことができます。

各「|」に「@」を追加して、列コマンドへの入力が「xxx @ | yyyy」になるこの例を参照してください。列は「@」を処理し、「|」は影響を受けません。

~$ echo "foo | this is some text | bar" | sed 's/|/@|/g'  | column -s '@' -t
foo   | this is some text   | bar

答え2

お問い合わせいただいた時点ではこの機能は使用できませんでしたが、セクション 2.23 基準 columnfromutil-linuxでは出力区切り文字を選択できます。

   -o, --output-separator string
          Specify the columns delimiter for table output (default is two spaces).

だから実行してください:

 column -s '|' -o '|' -t infile

答え3

これはbashスクリプトです。 "column -t"を使用せず、区切り文字はIFS(または少なくともawkのIFSビルド)なので、IFSとまったく同じように扱われます。デフォルトの区切り文字は$ ' \ t'です。

スクリプトは一番右のフィールドを完全に埋めます。
「列」はこれを行いません。このスクリプトは、
すべての列を入力してテーブルフレームを作成するように簡単に変更できます。

メモ。入力ファイルは2回処理する必要があります
(「列」もこれを行う必要があります)。
最初のステップは、列の最大幅を取得することです。
2番目のパスは拡張フィールド(各列)です。

いくつかのオプションを追加しました。明らかなバグを修正しました(変数の名前を変更する:(

  • -lインデントされたフィールドの左側のスペースを切り捨てます。
  • -r最も広いテキストよりも広いスペースを右側に切り捨てます(列の場合)。
  • -b -l および -r
  • -L 左出力区切り記号を追加
  • -R 右出力区切り記号を追加します。
  • -B -L および -R
  • -S 出力区切り記号を選択します。

#!/bin/bash
#
#   script [-F sep] [file]
#
#   If file is not specified, stdin is read 
#    
# ARGS ######################################################################
l=;r=;L=;R=;O=;F=' ' # defaults
for ((i=1;i<=${#@};i++)) ;do
  case "$1" in
    -- ) shift 1;((i--));break ;;
    -l ) l="-l";shift 1;((i-=1)) ;;        #  left strip whitespace
    -r ) r="-r";shift 1;((i-=1)) ;;        # right strip whitespace
    -b ) l="-l";r="-r";shift 1;((i-=1)) ;; # strip  both -l and -r whitespace
    -L ) L="-L";shift 1;((i-=1)) ;;        #  Left output delimiter is added
    -R ) R="-R";shift 1;((i-=1)) ;;        # Right output delimiter is added
    -B ) L="-L";R="-R";shift 1;((i-=1)) ;; # output Both -L and -R delimiters
    -F ) F="$2";shift 2;((i-=2)) ;; # source separator
    -O ) O="$2";shift 2;((i-=2)) ;; # output  separator. Default = 1st char of -F 
    -* ) echo "ERROR: invalid option: $1" 1>&2; exit 1 ;;
     * ) break ;;
  esac
done
#
if  [[ -z "$1" ]] ;then # no filename, so read stdin
  f="$(mktemp)"
  ifs="$IFS"; IFS=$'\n'; set -f # Disable pathname expansion (globbing)
  while read -r line; do
    printf "%s\n" "$line" >>"$f"
  done
  IFS="$ifs"; set +f # re-enable pathname expansion (globbing)
else
  f="$1"
fi
[[ -f "$f" ]] || { echo "ERROR: Input file NOT found:" ;echo "$f" ;exit 2 ; }
[[ -z "$F" ]] && F=' '        # input Field Separator string
[[ -z "$O" ]] && O="$F"       # output Field Separator
                 O="${O:0:1}" #   use  single char only

# MAIN ######################################################################
max="$( # get max length of each field/column, and output them
  awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" '
    BEGIN { if (F!="") FS=F }
    { for (i=1;i<=NF;i++) { 
        if (l=="-l") { sub("^[ \t]*","",$i) }
        if (r=="-r") { sub("[ \t]*$","",$i) }
        len=length($i); if (len>max[i]) { max[i]=len } 
        if (i>imax) { imax=i } 
      } 
    }
    END { for(i=1;i<=imax;i++) { printf("%s ",max[i]) } }
  ' "$f" 
)"

awk -vl="$l" -vr="$r" -vL="$L" -vR="$R" -vF="$F" -vO="$O" -v_max="$max" '
  BEGIN { if (F!="") FS=F; cols=split(_max,max," ") }
  { # Bring each field up to max len and output with delimiter
    printf("%s",L=="-L"?O:"")
    for(i=1;i<=cols;i++) { if (l=="-l") { sub("^[ \t]*","",$i) } 
                           if (r=="-r") { sub("[ \t]*$","",$i) }
      printf("%s%"(max[i]-length($i))"s%s",$i,"",i==cols?"":O) 
    } 
    printf("%s\n",R=="-R"?O:"")
  }
' "$f"

# END #######################################################################    
if  [[ -z "$1" ]] ;then # no filename, so stdin was used
  rm "$f"   # delete temp file
fi
exit

答え4

これは2段階の調整です。ヘルモントリウ回答、入力データから区切り文字を推測してハードコーディングする必要はありません。

  1. 空白で囲まれた英数字以外の単一文字への入力を解析し、最も一般的な文字でソートし、最も一般的な文字が割り当てられた区切り文字であるとします$d
  2. やや進行ヘルモノリウ答えはありますが、ASCIIを使用することです。無効@次の代わりにパディングでピーターのコメント。

コードは、ファイル名または入力を受け入れる関数です。標準入力:

algn() { 
    d="$(grep -ow '[^[:alnum:]]' "${1:-/dev/stdin}"  | \
         sort | uniq -c | sort -rn | sed -n '1s/.*\(.$\)/\1/p')" ;
    sed "s/ *$d */\x01$d /g" "${1:-/dev/stdin}"  | column -s $'\001' -t ;
}

出力algn foo(またはalgn < foo):

foo      | bar  | baz
abc def  | 12   | 23456

関連情報