次のデータがあります(実際のデータには50,000桁と8000行を超える)。
入力する:
1 11122
1 21121
2 22221
2 11122
3 21121
3 11122
同じ名前の最初の行の値の横に2番目の行の値を配置したいと思います。また、各値ペア間の区切り文字としては2つのスペースが必要であり、異なる値ペア間の区切り記号としてタブが必要です。出力は次のようになります。
出力:
1 1 2 1 1 1 1 2 2 2 1
2 2 1 2 1 2 1 2 2 1 2
3 2 1 1 1 1 1 2 2 1 2
どんな提案がありますか?
答え1
私はPerlを使い、次のようにonelinerとして実行します。
perl -wne 'sub parseline { ($id,$v) = split; return split //,$v };
@a = parseline();
print "$id\t";
$_ = <>;
@b = parseline();
for ($i=0; $i<@a; $i++) {
print "$a[$i] $b[$i]\t"
};
print "\n"' < input > output
説明する:
perl -wne
各入力行に対して残りのコマンドを実行します。sub parseline { .... }
入力を解析し、行の最初の数字を設定$id
し、残りは文字配列として返します。@a=parseline()
文字の最初の行は @a 配列に格納されます。- 次に印刷
$id
してTAB(\t
)を押します。 $_=<>; @b=parseline();
次の(偶数)行を読み、そのデータを配列に入れます。@b
for ($i=0; $i<@a; $i++) { print "$a[$i] $b[$i]\t" }
配列の各要素に対して、@a
要素、2つのスペース、配列の対応する要素を印刷してから、タブを@b
印刷します。print "\n"
最後に改行文字を印刷します- at startパラメーターのため、
-n
プロセス全体は3行、5行、7行の順に始まります。perl
< input > output
入力を読み取るファイルと出力を書き込むファイルを示します。
注:コードは各行の末尾に追加のタブを印刷します。クラウドソーシングを防ぎ、コードをより簡単に保つための読者の練習でこれを削除しました。また、コードでは、ペアの行が常に2つの行が順番に連続していると想定しています(例を参照)。
入力ファイルを1行ずつ処理するため、数千行にわたって簡単に線形に拡張できます。
答え2
pairwise
これは、モジュールの関数を使用して2つの配列をList:MoreUtils
連結し、IDが一致する行(最初のフィールド)が連続行にある必要がないMatija Nalisのスクリプトバージョンです。つまり、複数行に分けることができます。
#! /usr/bin/perl
use strict;
use warnings;
use List::MoreUtils qw(pairwise);
sub parseline { my ($id,$v) = split; return $id, split //,$v };
my %ID=();
while (<>) {
my ($id, @line) = parseline();
if ( !defined($ID{$id}) ) {
push @{ $ID{$id} }, @line ;
} else {
my @paired = pairwise { "$a $b" } @{ $ID{$id} }, @line;
print join("\t", $id, @paired), "\n";
delete $ID{$id};
};
};
$id
MNのparseline
サブルーチンは、グローバル変数を使用するのではなく、各行のIDと要素の配列を返すように変更されました。
$id
%ID
解析された各行のハッシュを格納するためのキーとして使用されます。与えられたものを最初に見るとき、解析された行配列()をハッシュに$id
保存し、次の行に移動します。@line
次に見ると、保存した配列を現在の配列@line
とペアで連結し、TABフィールド区切り文字を使用して印刷してからハッシュから$id
削除%ID
します。
man List::MoreUtils
この機能のしくみのpairwise
詳細については、リソースを参照してください。ちなみに、List::Util
さまざまList::MoreUtils
なリスト(配列とも呼ばれます)を実行するための2つの素晴らしいモジュールです。
出力:
$ ./zara.pl zara.txt
1 1 2 1 1 1 1 2 2 2 1
2 2 1 2 1 2 1 2 2 1 2
3 2 1 1 1 1 1 2 2 1 2