例えば。次のように出力されるファイルがあります(echo -e "var1\tvar2\t\var3\tvar4" > foo
で作成)。
$ cat foo
case elems meshing nlsys
uniform 2350 0.076662 2.78
non-conformal 348 0.013332 0.55
scale 318 0.013333 0.44
smarter 504 0.016666 0.64
submodel 360 .009999 0.40
unstruct-quad 640 0.019999 0.80
unstruct-tri 1484 0.01 0.88
私はこのような出力を好みます(ここではvim
と:set tabstop=14
を使用しました):
case elems meshing nlsys
uniform 2350 0.076662 2.78
non-conformal 348 0.013332 0.55
scale 318 0.013333 0.44
smarter 504 0.016666 0.64
submodel 360 .009999 0.40
unstruct-quad 640 0.019999 0.80
unstruct-tri 1484 0.01 0.88
Bashで$ tabs=15
を使用すると、cat
で同じ機能を利用できます(これを参照してください question )。この種のフォーマットを自動的に行うプログラムはありますか?ファイルをtabs
ingする前にcat
の値を試したくありません。
私は通常column
プログラムを使用します。これはDebianのbsdmainutils
というパッケージにあります。
_column -t foo
_
出力:
_case elems meshing nlsys
uniform 2350 0.076662 2.78
non-conformal 348 0.013332 0.55
scale 318 0.013333 0.44
smarter 504 0.016666 0.64
submodel 360 .009999 0.40
unstruct-quad 640 0.019999 0.80
unstruct-tri 1484 0.01 0.88
_
私のシステムのcolumn(1)
からの抜粋:
_...
-t Determine the number of columns the input contains and create a
table. Columns are delimited with whitespace, by default, or
with the characters supplied using the -s option. Useful for
pretty-printing displays.
...
_
いくつかのオプション:
var1=uniform var2=2350 var3=0.076662 var4=2.78
printf '%-15s %-10s %-12s %s\n' \
case elems messing nlsys \
"$var1" "$var2" "$var3" "$var4"
printf '%s\t%s\t%s\t%s\n' \
case elems messing nlsys \
"$var1" "$var2" "$var3" "$var4" |
expand -t 15,25,37
printf '%s\t%s\t%s\t%s\n' \
case elems messing nlsys \
"$var1" "$var2" "$var3" "$var4" |
column -t -s $'\t'
columnは非標準のコマンドです。一部の実装/バージョンは-sオプションをサポートしていません。入力に基づいて列の幅を計算しますが、すべての入力が入力されると表示を開始できることを意味します。 $'...'
は、zshおよびbashにもあるksh93構文です。
Zshの場合:
values=(
case elems messing nlsys
"$var1" "$var2" "$var3" "$var4"
)
print -arC4 -- "$values[@]"
column -t
の代わりにrs
を使用することもできます。
(x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")
-c
は入力列セパレーターを変更しますが、-c
だけで入力列セパレーターをタブに設定します。 -z
は、すべての列を同じ幅にする代わりに、各列の幅を列の最も長いエントリの幅に設定します。一部の行の最初の行よりも列が少ない場合は、-n
を追加します。
これを実行できる別のツールは、 eBayのTSVユーティリティ のtsv-pretty
です(免責事項:私は作成者です)。数値フィールドを小数点に並べる追加のステップが必要です。例えば:
$ tsv-pretty foo
case elems meshing nlsys
uniform 2350 0.076662 2.78
non-conformal 348 0.013332 0.55
scale 318 0.013333 0.44
smarter 504 0.016666 0.64
submodel 360 .009999 0.40
unstruct-quad 640 0.019999 0.80
unstruct-tri 1484 0.01 0.88
いくつかのフォーマットオプションがあります。たとえば、-u
はヘッダーに下線を付け、-f
はフィールドの浮動小数点数を同様に書式設定して読みやすくしています。
$ tsv-pretty foo -f -u
case elems meshing nlsys
---- ----- ------- -----
uniform 2350 0.076662 2.78
non-conformal 348 0.013332 0.55
scale 318 0.013333 0.44
smarter 504 0.016666 0.64
submodel 360 0.009999 0.40
unstruct-quad 640 0.019999 0.80
unstruct-tri 1484 0.010000 0.88
詳細は tsv-pretty reference を参照してください。
function printTable()
{
local -r delimiter="${1}"
local -r data="$(removeEmptyLines "${2}")"
if [[ "${delimiter}" != '' && "$(isEmptyString "${data}")" = 'false' ]]
then
local -r numberOfLines="$(wc -l <<< "${data}")"
if [[ "${numberOfLines}" -gt '0' ]]
then
local table=''
local i=1
for ((i = 1; i <= "${numberOfLines}"; i = i + 1))
do
local line=''
line="$(sed "${i}q;d" <<< "${data}")"
local numberOfColumns='0'
numberOfColumns="$(awk -F "${delimiter}" '{print NF}' <<< "${line}")"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]]
then
table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
fi
# Add Header Or Body
table="${table}\n"
local j=1
for ((j = 1; j <= "${numberOfColumns}"; j = j + 1))
do
table="${table}$(printf '#| %s' "$(cut -d "${delimiter}" -f "${j}" <<< "${line}")")"
done
table="${table}#|\n"
# Add Line Delimiter
if [[ "${i}" -eq '1' ]] || [[ "${numberOfLines}" -gt '1' && "${i}" -eq "${numberOfLines}" ]]
then
table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")"
fi
done
if [[ "$(isEmptyString "${table}")" = 'false' ]]
then
echo -e "${table}" | column -s '#' -t | awk '/^\+/{gsub(" ", "-", $0)}1'
fi
fi
fi
}
function removeEmptyLines()
{
local -r content="${1}"
echo -e "${content}" | sed '/^\s*$/d'
}
function repeatString()
{
local -r string="${1}"
local -r numberToRepeat="${2}"
if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
then
local -r result="$(printf "%${numberToRepeat}s")"
echo -e "${result// /${string}}"
fi
}
function isEmptyString()
{
local -r string="${1}"
if [[ "$(trimString "${string}")" = '' ]]
then
echo 'true' && return 0
fi
echo 'false' && return 1
}
function trimString()
{
local -r string="${1}"
sed 's,^[[:blank:]]*,,' <<< "${string}" | sed 's,[[:blank:]]*$,,'
}
サンプルラン
$ cat data-1.txt
HEADER 1,HEADER 2,HEADER 3
$ printTable ',' "$(cat data-1.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
$ cat data-2.txt
HEADER 1,HEADER 2,HEADER 3
data 1,data 2,data 3
$ printTable ',' "$(cat data-2.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
| data 1 | data 2 | data 3 |
+-----------+-----------+-----------+
$ cat data-3.txt
HEADER 1,HEADER 2,HEADER 3
data 1,data 2,data 3
data 4,data 5,data 6
$ printTable ',' "$(cat data-3.txt)"
+-----------+-----------+-----------+
| HEADER 1 | HEADER 2 | HEADER 3 |
+-----------+-----------+-----------+
| data 1 | data 2 | data 3 |
| data 4 | data 5 | data 6 |
+-----------+-----------+-----------+
$ cat data-4.txt
HEADER
data
$ printTable ',' "$(cat data-4.txt)"
+---------+
| HEADER |
+---------+
| data |
+---------+
$ cat data-5.txt
HEADER
data 1
data 2
$ printTable ',' "$(cat data-5.txt)"
+---------+
| HEADER |
+---------+
| data 1 |
| data 2 |
+---------+
REF LIB: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash
問題は、タブ区切りの列を出力することでした。
したがって、正しい答えは@nisetamaの答えを少し変更したものです。出力フォーマットを設定する-C $ '\ t'オプションを追加しました。
x=$(cat foo2); rs -C$'\t' $(wc -l <<<"$x") <<<"$x"
工藤は@nisetamaにも:)