탭으로 구분 된 열을 출력하는 간단한 명령이 있습니까?


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

bash에서 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.

...

큰! 고마워요! 이미 내 컴퓨터에 설치되었습니다.
Sebastian

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'

column은 비표준 명령이며 일부 구현 / 버전은 -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 명령이며 APL에서 형태 변경 기능의 이름을 따서 명명 된 OS X와 ​​함께 제공됩니다. 데비안 꾸러미 이름은 그대로 rs이므로 설치할 수 있습니다 apt-get install rs.
nisetama

명령을 (x=$(cat);rs -c -z $(wc -l<<<"$x")<<<"$x")어떻게 호출하는지에 대한 예를 제공 할 수 있습니까? 나는 그것을 CSV 파일과 함께 사용하는 방법을 모른다
baxx

3

이 작업을 수행 할 수있는 또 다른 도구입니다 tsv-pretty에서 이베이의 TSV 유틸리티 (면책 조항 : 나는 저자 해요). 소수점에 숫자 필드를 정렬하는 추가 단계가 필요합니다. 예를 들면 다음과 같습니다.

$ 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에 있습니다.


이것은 정말 도움이됩니다
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  |
+---------+

REF LIB : https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash


흥미로운 배쉬 전용 솔루션-공유해 주셔서 감사합니다
Sebastian

이것은 너무 복잡하다. 그리고 sed사용되는 것과 같은 외부 명령이 있기 때문에 bash 전용이 아닙니다 .
codeforester
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.