より良い貼り付けコマンド


11

私は次の2つのファイルを持っています(ファイルのすべての行が同じ幅になるように行にドットをパディングし、より明確にするために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
paste2番目のファイルの行の前にタブを使用しています。列を適切に配置するには、ポストプロセッサーを使用する必要がある場合があります。
unxnut 2013年

3
paste file1 file2 | column -tn
ninjalj 2013年

file1には常に固定サイズの列がありますか?
RSFalcon7 2013年

@ RSFalcon7はい、そうです。
TulainsCórdova2013

回答:


17

ファイルにタブ文字がないと仮定すると、

paste file1 file2 | expand -t 13

argを-t適切に選択して、file1の目的の最大行幅をカバーします。

OPはより柔軟なソリューションを追加しました:

私はこれを行ったので、マジックナンバー13がなくても機能します。

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

入力は簡単ではありませんが、スクリプトで使用できます。


いいね!私はあなたの答えを読む前に展開について知りませんでした:)
TabeaKischka

4

私はawkがうまくできると思ったので、「2つのファイルから入力を読み取るawk」をグーグル検索し、開始点として使用する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 2017

2

あまり良い解決策ではありませんが、私はそれを使用してそれを行うことができました

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

ここで、TABはタブ文字に置き換えられます。


&&sedコマンドでの役割は何ですか?
coffeMug ​​2013年

1
シングル&は検索対象(この場合はタブ)を配置します。このコマンドは、最初のタブを2つのタブに置き換えるだけです。
unxnut 2013年

Ubuntu debianのzshでこれを機能させるには、に変更TABする\t必要がありました。また、file1の
文字数

2

Debianとその派生物にcolumnは、カラムが空のフィールドで正しいことを行えるようにする-n nomergeオプションがあります。内部的にcolumnは、wcstok(wcs, delim, ptr)ワイド文字列をdelim引数のワイド文字で区切られたトークンに分割する関数を使用します。

wcstokdelimトークンを認識する前に、でワイド文字をスキップすることから始めます。この-nオプションは、の最初のワイド文字をスキップしないアルゴリズムを使用しdelimます。

残念ながら、これはあまり移植性がありません-n。Debian固有でありcolumn、POSIXにはありません。明らかに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 2017

+1。ソリューションがどのように機能するか説明していただけますか?
Tulainsコルドバ2017

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 2013年

私が得るawk: Line:1: (FILENAME=file1 FNR=1) Fatal: Division by zero
rubo77 2013年

@ rubo77:awk -f paste-awk file1 file2少なくともGNU awkとmawkでは機能するはずです。
ninjalj 2013

これは機能しpasteますが、2つの行の間のスペースが少ないこととは少し異なります。また、入力ファイルのすべての行が同じ長さではない場合、
右揃えの

@ rubo77:フィールド区切り記号は、次のように設定できます-F\\t
ninjalj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.