線を分割して並べ替え

線を分割して並べ替え

セミコロンで区切られた130個のフィールドを含むファイルがあります。何とか並べ替えたいです。

次の例を考えてみましょう。

文書サンプル.txt:

1;2;3;4;8;5;6;7;9;10;11;
11;12;13;14;18;15;16;17;19;20;21;

希望の出力(ファイル要求作業.txt):

1;2;3;4;5;6;7;8;9;10;11;
11;12;13;14;15;16;17;18;19;20;21;

8番目の要素の位置が間違っています。私がしたことはプロセスを単純化するだけでした。問題は、121のフィールドがあるため、きちんとしたAWKコマンドを使用してファイル全体に対して1行のテキストを操作できないことです。

私は次のことを試してみました。より効率的で読みやすいソリューションを提案できますか?お客様のソリューションの説明もお願いします。

各フィールドには、背中を含むスペース/文字で区切られた数字と文字列を含めることができます$#

#!/bin/bash

file="sample.txt"

while read -r line
do

    array=($(echo "$line" | sed 's/;/ /g'))

    printf -v first '%s;' "${array[@]:0:4}"
    printf -v last '%s;' "${array[@]:8:12}"
    printf -v second '%s;' "${array[@]:5:3}"
    printf -v third '%s;' "${array[@]:4:1}"

    echo "${first}${second}${third}${last}" >> req_op.txt

done < $file

実際のフィールド数:

入力する:

1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|143|138|139|140|141|142|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162

出力:

1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162

@Quasímodoが共有したsedコマンドを修正しました。これで期待どおりに動作します。

sed -E 's~(([^\|]*\|){137})([^\|]*\|)(([^\|]*\|){5})~\1\4\3~' sample.txt

答え1

パールの使用:

$ perl -F';' -lne 'splice @F, 7, 0, (splice @F, 4, 1); print join ";", @F' sample.txt 
1;2;3;4;5;6;7;8;9;10;11
11;12;13;14;15;16;17;18;19;20;21

例を見るPerlでのスライスとダイシングされたアレイの接続

答え2

awkを使う

awk 'BEGIN{FS=OFS=";"}{$8=$8 FS $5;$5=RS;sub(RS FS,"");print}' sample.txt > req_op.txt

説明を含む拡張バージョン:

awk '
  BEGIN{FS=OFS=";"} #Sets input (FS) and output (OFS) field separators
  {                 #For each line
    $8=$8 FS $5     #Append the 5th field after the 8th field
    $5=RS           #Put a newline (the record separator) in the 5th field
    sub(RS FS,"")   #Remove the newline and its following FS
    print           #Print the resulting line
  }     
' sample.txt > req_op.txt

5番目のフィールドを一時的に置き換えるためにレコード区切り文字(あなたの場合は改行)を選択したのはなぜですか?確かに記録に残らない唯一のキャラクターだからです。その後、sub(RS FS,"")どこかに空のフィールドがあっても、5番目のフィールドを必ず削除してください。

その行がわからない場合は、その行をsub削除して出力に何が起こるかを確認してください。

Sedを使う

  • 拡張正規表現を使用してください。

    sed -E 's|(([^;]*;){4})([^;]*;)(([^;]*;){3})|\1\4\3|' sample.txt > req_op.txt
    
  • POSIXに準拠したデフォルトの正規表現を使用すると、基本的に上記と同じですが、それぞれ(){}エスケープが必要です(ため息!)。

    sed 's|\(\([^;]*;\)\{4\}\)\([^;]*;\)\(\([^;]*;\)\{3\}\)|\1\4\3|' sample.txt > req_op.txt
    

ssed の代替コマンドです。その後の文字は区切り記号です(私が選択したもの|)。正規表現スロット、代替スロット、およびフラグスロット(この場合は空)を定義します。

正規表現のいくつかの要素は次のとおりです。

  • [^;]*;:セミコロン以外の文字が0個以上表示され、その後にセミコロンが続きます。
  • ([^;]*;){4}:上記の表現はキャプチャグループに属し、正確に4回繰り返す必要があります。
  • (([^;]*;){4})\1:上記の式は外部キャプチャグループにあり、代替式で再現されます。内部キャプチャグループが置き換えられます\2

したがって、最初の行で何が起こるかは1;2;3;4;8;5;6;7;9;10;11;次のとおりです。

  • \1得る1;2;3;4;
  • \3得る8;
  • \4得る5;6;7;

に並べ替えられます\1\4\3

逆参照の詳細については、次を参照してください。パターンの一部を保存するには\ 1を使用してください。 (ところで、このページは良いsedチュートリアルです。)

答え3

を使用すると、perl次の操作も実行できます。

perl -F';' -lape '$_ = join ";", @F[0..3,5..7,4,8..10]' sample

またはあなたのために実際入力する:

perl -F'[|]' -lape '$_ = join "|", @F[0..136,138..142,137,143..161]' input

答え4

Python

#!/usr/bin/python
k=open('filename','r')
r=[]
v=[]
for i in k:
    r=[]
    v=[]
    j=i.strip().split(";")
    for g in j:
        if (g != ''):
            r.append(int(g.strip()))
    r.sort()
    e=r
    for d in e:
        v.append(str(d))
        v.append(str(";"))
    print "".join(v)

出力

1;2;3;4;5;6;7;8;9;10;11;
11;12;13;14;15;16;17;18;19;20;21;

関連情報