더 나은 붙여 넣기 명령


11

다음 두 파일이 있습니다 (파일의 모든 줄이 같은 너비가되도록 file1을 모두 대문자로 지정하여 더 명확하게하기 위해 점으로 선을 채웠습니다).

contents of file1:

ETIAM......
SED........
MAECENAS...
DONEC......
SUSPENDISSE

contents of file2

Lorem....
Proin....
Nunc.....
Quisque..
Aenean...
Nam......
Vivamus..
Curabitur
Nullam...

file2가 file1보다 깁니다.

이 명령을 실행할 때 :

paste file1 file2

이 결과를 얻습니다

ETIAM...... Lorem....
SED........ Proin....
MAECENAS... Nunc.....
DONEC...... Quisque..
SUSPENDISSE Aenean...
    Nam......
    Vivamus..
    Curabitur
    Nullam...

출력을 다음과 같이하려면 어떻게해야합니까?

ETIAM...... Lorem....
SED........ Proin....
MAECENAS... Nunc.....
DONEC...... Quisque..
SUSPENDISSE Aenean...
            Nam......
            Vivamus..
            Curabitur
            Nullam...

나는 시도했다

paste file1 file2 | column -t

그러나 이것은 이렇게합니다 :

ETIAM......  Lorem....
SED........  Proin....
MAECENAS...  Nunc.....
DONEC......  Quisque..
SUSPENDISSE  Aenean...
Nam......
Vivamus..
Curabitur
Nullam...

어쨌든 원래 출력만큼 ​​추악하지는 않지만 열 방향으로 잘못되었습니다.


2
paste두 번째 파일의 줄 앞에 탭을 사용하고 있습니다. 열을 적절하게 맞추려면 포스트 프로세서를 사용해야 할 수도 있습니다.
unxnut

3
paste file1 file2 | column -tn?
ninjalj

file1에는 항상 고정 크기 열이 있습니까?
RSFalcon7

@ RSFalcon7 그렇습니다.
Tulains Córdova

답변:


17

파일에 탭 문자가 없다고 가정하면,

paste file1 file2 | expand -t 13

-tfile1에서 원하는 최대 행 너비를 포함 하도록 arg를 적절하게 선택합니다.

OP는보다 유연한 솔루션을 추가했습니다.

나는 이것을 마법의 숫자 13없이 작동하도록했다.

paste file1 file2 | expand -t $(( $(wc -L <file1) + 2 ))

입력하기 쉽지 않지만 스크립트에서 사용할 수 있습니다.


좋은! 나는 당신의 답변을 읽기 전에 확장에 대해 몰랐습니다 :)
TabeaKischka

4

나는 awk가 잘 할 것이라고 생각했기 때문에 "두 개의 파일에서 입력을 읽는 중"을 Google 로 검색하고 stackoverflow대한 기사를 시작점으로 사용했습니다.

첫 번째는 압축 버전이며 그 아래에 완전히 주석이 달렸습니다. 운동하는 데 몇 분 이상이 걸렸습니다. 더 똑똑한 사람들의 개선점에 기뻐할 것입니다.

awk '{if(length($0)>max)max=length($0)}
FNR==NR{s1[FNR]=$0;next}{s2[FNR]=$0}
END { format = "%-" max "s\t%-" max "s\n";
  numlines=(NR-FNR)>FNR?NR-FNR:FNR;
  for (i=1; i<=numlines; i++) { printf format, s1[i]?s1[i]:"", s2[i]?s2[i]:"" }
}' file1 file2

그리고 여기에 위의 완전한 문서화 된 버전이 있습니다.

# 2013-11-05 mike@diehn.net
# Invoke thus:
#   awk -f this_file file1 file2
# The result is what you asked for and the columns will be
# determined by input file order.
#----------------------------------------------------------
# No matter which file we're reading,
# keep track of max line length for use
# in the printf format.
#
{ if ( length($0) > max ) max=length($0) }

# FNR is record number in current file
# NR is record number over all
# while they are equal, we're reading the first file
#   and we load the strings into array "s1"
#   and then go to the "next" line in the file we're reading.
FNR==NR { s1[FNR]=$0; next }

# and when they aren't, we're reading the
#   second file and we put the strings into
#   array s2
{s2[FNR]=$0}

# At the end, after all lines from both files have
# been read,
END {
  # use the max line length to create a printf format
  # the right widths
  format = "%-" max "s\t%-" max "s\n"
  # and figure the number of array elements we need
  # to cycle through in a for loop.
  numlines=(NR-FNR)>FNR?NR-FNR:FNR;
  for (i=1; i<=numlines; i++) {
     printf format, s1[i]?s1[i]:"", s2[i]?s2[i]:""
  }
}

1
+1 이것은 임의의 입력 (즉, 탭을 포함 할 수있는 줄)에서 작동하는 유일한 대답입니다. 나는 이것이 상당히 개선되거나 향상 될 수 있다고 생각하지 않습니다.
don_crissti

2

아주 좋은 해결책은 아니지만 사용하여 할 수있었습니다.

paste file1 file2 | sed 's/^TAB/&&/'

여기서 TAB은 탭 문자로 바뀝니다.


&&sed 명령 의 역할은 무엇입니까 ?
coffeMug

1
하나 &는 검색 대상을 넣습니다 (이 경우 탭). 이 명령은 처음에 탭을 두 개의 탭으로 바꿉니다.
unxnut

우분투 데비안에서 zsh 로이 작업을 수행 하도록 변경 TAB해야 \t했습니다. 파일 1가 15 개 미만의 문자가있는 경우 그리고 그것은 단지 작업을 수행
rubo77을

2

데비안과 파생물 column에는 열이 빈 필드로 올바른 일을 할 수 있도록 -n nomerge 옵션이 있습니다. 내부적 으로 넓은 문자열을 인수 의 넓은 문자로 구분 된 토큰으로 나누는 함수를 column사용합니다 .wcstok(wcs, delim, ptr)delim

wcstokdelim토큰을 인식하기 전에 에서 넓은 문자를 건너 뛰어 시작합니다 . 이 -n옵션은의 초기 와이드 문자를 건너 뛰지 않는 알고리즘을 사용합니다 delim.

불행히도, 이것은 이식성이 좋지 않습니다 : -n데비안 전용이며 columnPOSIX에는 없으며 BSD 일 것입니다.


2

패딩에 사용한 점 제거

file1 :

ETIAM
SED
MAECENAS
DONEC
SUSPENDISSE

file2 :

Lorem
Proin
Nunc
Quisque
Aenean
Nam
Vivamus
Curabitur
Nullam

이 시도:

$ ( echo ".TS"; echo "l l."; paste file1 file2; echo ".TE" ) | tbl | nroff | more

그리고 당신은 얻을 것이다 :

ETIAM         Lorem
SED           Proin
MAECENAS      Nunc
DONEC         Quisque
SUSPENDISSE   Aenean
              Nam
              Vivamus
              Curabitur
              Nullam

이것은 다른 솔루션과 마찬가지로 paste탭이 포함 된 줄이 있으면 올바른 출력을 인쇄하지 못합니다. 다르지만 +1
don_crissti

+1. 솔루션 작동 방식을 설명해 주시겠습니까?
Tulains Córdova

1

awk상당히 휴대해야하고, 입력 파일의 임의의 수에 대해 작동한다 용액 :

# Invoke thus:
#   awk -F\\t -f this_file file1 file2

# every time we read a new file, FNR goes to 1

FNR==1 {
    curfile++                       # current file
}

# read all files and save all the info we'll need
{
    column[curfile,FNR]=$0          # save current line
    nlines[curfile]++               # number of lines in current file
    if (length > len[curfile])
            len[curfile] = length   # max line length in current file
}

# finally, show the lines from all files side by side, as a table
END {
    # iterate through lines until there are no more lines in any file
    for (line = 1; !end; line++) {
            $0 = _
            end = 1

            # iterate through all files, we cannot use
            #   for (file in nlines) because arrays are unordered
            for (file=1; file <= curfile; file++) {
                    # columnate corresponding line from each file
                    $0 = $0 sprintf("%*s" FS, len[file], column[file,line])
                    # at least some file had a corresponding line
                    if (nlines[file] >= line)
                            end = 0
            }

            # don't print a trailing empty line
            if (!end)
                    print
    }
}

file1과 file2에서 이것을 어떻게 사용합니까? 나는 스크립트를 호출 paste-awk하고 노력 paste file1 file2|paste-awk나는 시도 awk paste-awk file1 file2했지만 아무도 일하지.
rubo77

나는 얻을awk: Line:1: (FILENAME=file1 FNR=1) Fatal: Division by zero
rubo77

@ rubo77 : awk -f paste-awk file1 file2적어도 GNU awk 및 mawk에는 작동해야합니다.
ninjalj

paste두 행 사이의 공간이 적다는 것과 약간 다르지만 작동 합니다. 입력 파일이 모든 행에 같은 길이를 가지고 있다면, 그것은 정렬 오른쪽 행에 발생합니다
rubo77

@ rubo77 : 필드 구분 기호는 다음과 같이 설정할 수 있습니다-F\\t
ninjalj
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.