มีคำสั่งง่ายๆสำหรับการแสดงผลคอลัมน์ที่คั่นด้วยแท็บหรือไม่


67

เช่นฉันมีไฟล์ (ผลิตด้วย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

ฉันสามารถใช้ฟังก์ชันการทำงานเดียวกันได้catถ้าฉันใช้เป็น$ tabs=15bash (ดูคำถามนี้) มีโปรแกรมที่จัดรูปแบบเช่นนี้โดยอัตโนมัติหรือไม่? ฉันไม่ต้องการทดสอบกับtabsค่าก่อนcatนำเข้าไฟล์

คำตอบ:


87

ฉันมักจะใช้columnโปรแกรมนี้มันอยู่ในแพ็คเกจที่เรียกว่าbsdmainutilsDebian:

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.

...

ที่ดี! ขอบคุณมาก! ติดตั้งไว้แล้วในเครื่องของฉัน
เซบาสเตียน

11
คุณอาจต้องการเพิ่ม-s $'\t'(ไม่พบในทุกการใช้งานคอลัมน์) ในกรณีที่เขตข้อมูลบางแห่งมีช่องว่าง
Stéphane Chazelas

2
@RakholiyaJenish $'\t'หมายถึงอักขระแท็บ ขึ้นบรรทัดใหม่$'\n'เป็นต้น
Manwe

2
column -ts: /etc/passwdผมใช้วิธีนี้เป็น ดูดี!
kyb

1
@kyb: ดูดียิ่งขึ้นด้วย-nเช่นหลีกเลี่ยงการรวมตัวคั่นที่อยู่ติดกันหลายตัว
Thor

10

หลายตัวเลือก:

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'

คอลัมน์เป็นคำสั่งที่ไม่ได้มาตรฐานการใช้งาน / รุ่นบางอย่างไม่สนับสนุนตัวเลือก -s มันคำนวณความกว้างของคอลัมน์ตามอินพุต แต่นั่นหมายความว่ามันสามารถเริ่มแสดงผลได้เมื่ออินพุตทั้งหมดถูกป้อนเข้าเท่านั้น $'...'เป็น ksh93 พบไวยากรณ์ใน zsh และ bash

ด้วย zsh:

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

4

คุณยังสามารถใช้rsเป็นทางเลือกในการcolumn -t:

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

-cเปลี่ยนตัวคั่นคอลัมน์อินพุต แต่-cตั้งค่าตัวคั่นคอลัมน์อินพุตเพียงอย่างเดียวให้เป็นแท็บ -zกำหนดความกว้างของแต่ละคอลัมน์เป็นความกว้างของรายการที่ยาวที่สุดของคอลัมน์แทนที่จะทำให้คอลัมน์ทั้งหมดมีความกว้างเท่ากัน -nถ้าเส้นบางมีคอลัมน์น้อยกว่าบรรทัดแรกเพิ่ม


ที่rsว่าคืออะไร? ฉันไม่ได้ติดตั้งคำสั่งนั้นบน CentOS หรือระบบ Ubuntu / Mint ของฉัน
Anthon

1
@Anthon มันเป็นคำสั่ง BSD ที่มาพร้อมกับ OS X ซึ่งตั้งชื่อตามฟังก์ชั่นการก่อร่างใหม่ใน APL ชื่อแพคเกจ Debian เป็นเพียงเพื่อให้คุณสามารถติดตั้งได้กับrs apt-get install rs
nisetama

คุณสามารถให้ตัวอย่างของวิธีการหนึ่งที่จะเรียกคำสั่ง(x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")หรือไม่ ฉันไม่รู้ว่าฉันจะใช้ไฟล์นั้นกับไฟล์ csv ได้อย่างไร
baxx

3

เครื่องมืออีกอย่างที่สามารถทำได้คือtsv-prettyจากTSV Utilities ของ eBay (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียน) ใช้ขั้นตอนเพิ่มเติมของการเรียงแถวฟิลด์ตัวเลขบนจุดทศนิยม ตัวอย่างเช่น:

$ 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 สวย


สิ่งนี้มีประโยชน์จริง ๆ
Arefe

1

คำถามคือเกี่ยวกับการแสดงผลคอลัมน์ที่คั่นด้วยแท็บ

ดังนั้นคำตอบที่ถูกต้องคือการปรับคำตอบเล็ก ๆ ของ @nisetama ฉันเพิ่มตัวเลือก -C $ '\ t' ซึ่งตั้งค่าการจัดรูปแบบผลลัพธ์

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

Kudo ถึง @nisetama ว่า :)


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

เรียกใช้ตัวอย่าง

$ 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  |
+---------+

อ้างอิง LIB ได้ที่: https://github.com/gdbtek/linux-cookbooks/blob/master/lไลบรารี/util.bash


วิธีแก้ปัญหา bash-only ที่น่าสนใจ - ขอบคุณสำหรับการแบ่งปัน
Sebastian

นี่ซับซ้อนเกินไป และมันไม่ได้เป็น bash-only เนื่องจากมีคำสั่งภายนอกเช่นsedการใช้
codeforester
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.