テキストファイル内の特定の列の文字列値を分割する方法

テキストファイル内の特定の列の文字列値を分割する方法

Linuxシステムには2つの列を持つテキストファイルがあります。

  • 1列= id_no(ほとんど5桁、一部は6桁)。
  • 列2 = Genetic_markers(全長50674ビット)。
12345 0102010205
54322 2221110051
123456 1122011510

ファイルを次のように変更したいと思います。

 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0
  1. 最初の列を数字に示すように右側に揃えるようにどのように変更できますか?

  2. 2番目の列の数字の間のスペースを変更する最も安定した方法を教えることができる人はいますか?コードの要素とその機能を説明してください。

ありがとう

答え1

そしてperl

$ perl -lane 'printf "%6s %s\n", $F[0], join " ", split "", $F[1]' <your-file
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

-lane(を使用する-nと、一度に1つのレコードを読み取り、wkは行をフィールドに分割し、レコードからine区切り文字を削除するため、-eレコードを使用して式を実行します。)次のように動作します。$_-aa@F-llperlawk

ここではprintf、空白を使用して最初のフィールドの長さを6に左詰め、次にスペースを使用してjoin2番目のフィールドを文字コンポーネントに分割します。

答え2

右揃えをするには、ファイル内で最も長い数字の長さを見つけるか、単に大きな数字を選んで使用します。たとえば、10 個のスペースを埋めることができます。

$ printf '%d\n' 123
123
$ printf '%10d\n' 123
       123

このアプローチが十分であれば、次のことができます。

$ awk '{ gsub(/./," &",$2); printf "%10d%s\n",$1,$2}' file 
     12345 0 1 0 2 0 1 0 2 0 5
     54322 2 2 2 1 1 1 0 0 5 1
    123456 1 1 2 2 0 1 1 5 1 0

ここでは2つのことだけが起こっています。

  • gsub(/./," &",$2);:これgsubGグローバル息子.stitution)関数は、ユーザーが提供した正規表現のすべての項目をユーザーが提供した代替項目に置き換えます(ここでは「すべての文字」という意味のみを与えます)。&「正規表現と一致するすべて」を意味する特別な意味を持つので、&代替効果は各文字の前にスペースを挿入することです。最後のパラメータは入力で、ここでは2番目のフィールドを提供します$2
  • printf "%10d %s\n",$1,$2printf:フォーマットされた文字列を印刷するために使用します。%10dこれは「私が与えた数字を印刷して10個の空白で埋めます」を意味し、%sこれは「この文字列を印刷します」を意味します。だから私たちは10の空白で埋められた最初のフィールドを印刷し、修正された2番目のフィールドを印刷するように指示しますgsub

最小値のみを入力するには、ファイルを2回読み取る必要があります。最初に最長の最初のフィールドの長さを取得します。

$ awk -v max=0 '{ if(length($1) > max){ max=length($1) }} END{print max}' file 
6

これにより、より具体的に説明できます。

$ awk '{ k=gsub(/./," &",$2); printf "%6d%s\n",$1,$2}' file 
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

答え3

awkanyとGNUを使用column(用-R):

$ awk '{gsub(/./," &",$2)} 1' file | column -tR1
 12345  0  1  0  2  0  1  0  2  0  5
 54322  2  2  2  1  1  1  0  0  5  1
123456  1  1  2  2  0  1  1  5  1  0

-o' 'フィールド間のスペースが本当に重要な場合は、以下を追加してください。

$ awk '{gsub(/./," &",$2)} 1' file | column -o' ' -t -R1
 12345 0 1 0 2 0 1 0 2 0 5
 54322 2 2 2 1 1 1 0 0 5 1
123456 1 1 2 2 0 1 1 5 1 0

答え4

使用幸せ(以前のPerl_6)

~$ raku -ne '.split(" ") andthen put sprintf("%6d", .[0]), .[1].comb;'  file 

#OR

~$ raku -ne '.words andthen put sprintf("%6d", .[0]), .[1].comb;'  file

RakuはPerlファミリーのプログラミング言語です。上記は、Rakuの-ne非自動印刷ライン別フラグを使用しています。デフォルトでは、この-nフラグは行末から区切り文字を削除します。その後、print末尾の改行文字(デフォルト)を省略するか、これにより後続のput改行文字が追加されます(putターミネーターを使用した印刷)。

最初の答えでは、その行は明らかに単一の.split空白(の略語$_.split)にあります。 2番目の答えは、Rakuの.wordsルーチンをスペースに分割するために使用されます。その後、各列の出力形式を指定できるように接続がandthen再ロードされます。$_最初の列(例.[0]:)はフォーマットされ、sprintf2番目の列(たとえば.[1])はcomb単一文字で編集されて返されます。


注:「ID」が実際には(10進数)符号なし整数の場合は、内部的にに示されているように代わりにsprintf使用できます。udsprintf("%6u", …)


入力例:

12345 0102010205
54322 2221110051
123456 1122011510

出力例:

 123450 1 0 2 0 1 0 2 0 5
 543222 2 2 1 1 1 0 0 5 1
1234561 1 2 2 0 1 1 5 1 0

注:ファイルに空白行が含まれているときにエラーが発生するのを防ぐために、if空白行を削除する条件を追加できます。

~$ raku -ne 'if .chars { .words andthen put sprintf("%6d", .[0]), .[1].comb};'  file

#OR

~$ raku -ne 'if $_ .= words {put sprintf("%6d", .[0]), .[1].comb};'  file

空行を維持するには、Raku'sを使用できます。3元オペレーター:

~$ raku -ne '.chars ??  ( .split(" ") andthen put sprintf( "%6d", .[0]), .[1].comb) !! "".put;'  file

#OR

~$ raku -ne '$_ .= split(" ", :skip-empty) ?? (put sprintf( "%6d", .[0]), .[1].comb) !! "".put;'  file 

https://docs.raku.org/routine/sprintf
https://docs.raku.org/routine/%3F%3F%20%21%21
https://raku.org

関連情報