Có một lệnh đơn giản để xuất các cột được phân định bằng tab không?


67

Ví dụ: tôi có một tệp (được tạo với echo -e "var1\tvar2\t\var3\tvar4" > foo) có đầu ra là:

$ 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

Tôi thích đầu ra như thế này (ở đây tôi đã sử dụng 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

Tôi có thể có được chức năng tương tự catnếu tôi sử dụng $ tabs=15trong bash (xem câu hỏi này ). Có một chương trình thực hiện loại định dạng này tự động? Tôi không muốn thử nghiệm tabsgiá trị trước khi nhập cattệp.

Câu trả lời:


87

Tôi thường sử dụng columnchương trình này, nó nằm trong gói có tên bsdmainutilstrên Debian:

column -t foo

Đầu ra:

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

Trích từ column(1)trên hệ thống của tôi:

...

-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.

...

tuyệt quá! cảm ơn rất nhiều! Nó đã được cài đặt trên máy của tôi.
Sebastian

11
bạn có thể muốn thêm -s $'\t'(không tìm thấy trong mọi triển khai cột) trong trường hợp một số trường có chứa khoảng trắng.
Stéphane Chazelas

2
@RakholiyaJenish $'\t'có nghĩa là nhân vật tab. Dòng mới là $'\n'như vậy.
Manwe

2
Tôi đã sử dụng điều này như column -ts: /etc/passwd. Trông mát mẻ!
kyb

1
@kyb: trông thậm chí còn tốt hơn với -n, tức là tránh hợp nhất nhiều dấu phân cách liền kề
Thor

10

Một vài lựa chọn:

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'

cột là một lệnh không chuẩn, một số triển khai / phiên bản không hỗ trợ tùy chọn -s. Nó tính toán độ rộng của cột dựa trên đầu vào, nhưng điều đó có nghĩa là nó chỉ có thể bắt đầu hiển thị khi tất cả đầu vào đã được cung cấp cho nó. $'...'cú pháp ksh93 cũng được tìm thấy trong zsh và bash.

Với zsh:

values=(
  case elems messing nlsys
  "$var1" "$var2" "$var3" "$var4"
)
print -arC4 -- "$values[@]"

4

Bạn cũng có thể sử dụng rsthay thế cho column -t:

(x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")

-cthay đổi dấu tách cột đầu vào, nhưng -cmột mình đặt dấu tách cột đầu vào thành một tab. -zđặt chiều rộng của mỗi cột thành chiều rộng của mục nhập dài nhất của cột thay vì làm cho tất cả các cột có cùng chiều rộng. Nếu một số dòng có ít cột hơn dòng đầu tiên, hãy thêm -n.


Đó rslà cái gì Tôi chưa cài đặt lệnh đó trên CentOS cũng như các hệ thống Ubuntu / Mint của mình.
Anthon

1
@Anthon Đây là lệnh BSD cũng đi kèm với OS X, được đặt tên theo chức năng định hình lại trong APL. Tên gói Debian chỉ là rs, vì vậy bạn có thể cài đặt nó với apt-get install rs.
nisetama

bạn có thể cung cấp một ví dụ về cách người ta sẽ gọi lệnh (x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")? Tôi không biết làm thế nào tôi có thể sử dụng nó với tệp csv
baxx

3

Một công cụ khác có thể làm điều này là tsv-prettytừ Tiện ích TSV của eBay (từ chối trách nhiệm: Tôi là tác giả). Nó thực hiện bước bổ sung xếp hàng các trường số trên dấu thập phân. Ví dụ:

$ 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

Có một số tùy chọn định dạng. Ví dụ: -ugạch chân tiêu đề và -fđịnh dạng các float trong một trường tương tự để dễ đọc:

$ 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

Thông tin thêm có sẵn trong tài liệu tham khảo khá tsv .


Điều này thực sự hữu ích
Arefe

1

Câu hỏi là về việc xuất các cột được phân định bằng tab.

Vì vậy, câu trả lời đúng là một sự điều chỉnh nhỏ cho câu trả lời của @nisetama. Tôi đã thêm tùy chọn -C $ '\ t' để định dạng đầu ra.

x=$(cat foo2); rs -C$'\t' $(wc -l <<<"$x") <<<"$x"

Kudo là @nietama mặc dù :)


1
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:]]*$,,'
}

MẪU CHẠY

$ 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 tại: https://github.com/gdbtek/linux-cookbooks/blob/master/lologists/util.bash


giải pháp chỉ bash thú vị - cảm ơn vì đã chia sẻ
Sebastian

Điều này là quá phức tạp. Và nó không phải là bash-only vì có các lệnh bên ngoài như sedđược sử dụng.
codeforester
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.