क्या टैब-सीमांकित स्तंभों के आउटपुट के लिए एक सरल आदेश है?


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=15बैश में उपयोग करता हूं (यह प्रश्न देखें )। क्या कोई ऐसा कार्यक्रम है जो इस तरह का स्वरूपण स्वचालित रूप से करता है? मैं फ़ाइल में प्रवेश करने tabsसे पहले मान के साथ प्रयोग नहीं करना चाहता cat

जवाबों:


87

मैं आमतौर पर इसके लिए columnप्रोग्राम का उपयोग करता हूं , यह 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.

...

महान! आपका बहुत बहुत धन्यवाद! यह मेरी मशीन पर पहले से इंस्टॉल था।
सेबस्टियन

11
-s $'\t'यदि कुछ फ़ील्ड्स में रिक्तियाँ हैं, तो आप (प्रत्येक स्तंभ कार्यान्वयन में नहीं मिला है) जोड़ना चाह सकते हैं ।
स्टीफन चेजलस 15

2
@ राखोलियाजैनिश का $'\t'मतलब है टैब कैरेक्टर। नई लाइन वगैरह है $'\n'
मनेवे

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 सिस्टम पर।
एंथन

1
@Anthon यह एक BSD कमांड है जो OS X के साथ आता है, जिसका नाम APL में रिशेप फंक्शन के नाम पर है। डेबियन पैकेज का नाम बस है rs, इसलिए आप इसे स्थापित कर सकते हैं apt-get install rs
निसेटमा

क्या आप इस बात का उदाहरण दे सकते हैं कि कोई कैसे कमांड को कॉल करेगा (x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")? मुझे नहीं पता कि मैं एक सीएसवी फ़ाइल के साथ उस का उपयोग करने के बारे में कैसे
जाऊंगा

3

एक और उपकरण जो ऐसा कर सकता है 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- सुंदर संदर्भ में उपलब्ध है ।


यह वास्तव में उपयोगी है
Arefe

1

सवाल टैब सीमांकित कॉलम के आउटपुट के बारे में था।

तो सही उत्तर @nisetama के उत्तर का एक छोटा सा अनुकूलन है। मैंने -C $ '\ t' विकल्प जोड़ा, जो आउटपुट स्वरूपण सेट करता है।

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

कूडो के @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  |
+---------+

REF LIB यहां: https://github.com/gdbtek/linux-cookbooks/blob/master/lbooks/util.bash


दिलचस्प बैश-केवल समाधान - साझा करने के लिए धन्यवाद
सेबस्टियन

यह बहुत जटिल है। और यह बाश नहीं है-केवल इसलिए कि बाहरी आदेशों का sedउपयोग किया जा रहा है।
कोडवर्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.