30番目のタブまたは88番目のスペースから始めて、ファイルの最後の3列をフォーマットする方法

30番目のタブまたは88番目のスペースから始めて、ファイルの最後の3列をフォーマットする方法

Ubuntu 16.04 GNU bash、バージョン4.4.0

1,264,524行の郵便番号を含むこのテキストファイルの形式を指定したいと思います。

#!/bin/bash

wget http://download.geonames.org/export/zip/allCountries.zip
unzip allCountries.zip
mv -f allCountries.txt .allCountries.txt
rm -f allCountries.zip

これはファイルのフォーマットされていない部分です。

AD AD100 Canillo                    42.5833  1.6667   6
AD AD200 Encamp                     42.5333  1.6333   6
AD AD300 Ordino                     42.6  1.55  6
AD AD400 La Massana                    42.5667  1.4833   6
AD AD500 Andorra la Vella                    42.5  1.5   6
AD AD600 Sant Julià de Lòria                    42.4667  1.5   6
AD AD700 Escaldes-Engordany                     42.5  1.5667   6
AR 3636  POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S))  Salta A              -23.4933 -61.9267 3
AR 4123  LAS SALADAS Salta A              -25.7833 -64.5 4
AR 4126  BARADERO Salta A              -26.0833 -65.263  3
AR 4126  EL CUIBAL   Salta A              -26.0833 -65.263  3
AR 4126  LA ASUNCION Salta A              -26.0833 -65.263  3
AR 4126  MIRAFLORES (TALA, DPTO. CANDELARIA) Salta A              -26.0833 -65.263  3
AR 4141  TOLOMBON Salta A              -26.2 -65.9167 4
AR 4141  QUISCA GRANDE  Salta A              -26.4367 -65.97   3
AR 4141  LA CIENEGUITA  Salta A              -26.4367 -65.97   3
AR 4141  MACHO RASTROJO Salta A              -26.4367 -65.97   3
AR 4190  ROSARIO DE LA FRONTERA  Salta A              -25.8 -64.9667 4
AR 4190  OVANDO   Salta A              -25.8 -65.1 4
AR 4190  SAN ESTEBAN Salta A              -25.8 -65.0333 3
AR 4190  LA BANDA (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA)  Salta A              -25.8 -65.0333 3
AR 4190  LA MATILDE  Salta A              -25.8 -65.0333 3
AR 4190  LAS PIEDRITAS  Salta A              -25.8 -65.0333 3
AR 4190  LOS POCITOS Salta A              -25.8 -65.0333 3
AR 4190  OJO DE AGUA (ROSARIO DE LA FRONTERA, DPTO. R.DE LA FRONTERA)   Salta A              -25.8 -65.0333 3
AR 4190  POTRERILLO (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA)   Salta A              -25.8 -65.0333 3

最終結果は次のとおりです。

AD AD100 Canillo                                                                          42.5833     1.6667      6
AD AD200 Encamp                                                                           42.5333     1.6333      6
AD AD300 Ordino                                                                           42.6        1.56        6
AD AD400 La Massana                                                                       42.5667     1.4833      6
AD AD500 Andorra la Vella                                                                 42.5        1.6         6
AD AD600 Sant Julià de Lòria                                                              42.4667     1.5         6
AD AD700 Escaldes-Engordany                                                               42.5        1.5667      6
AR 3636  POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S))  Salta A                       -23.4933    -61.9267    3
AR 4123  LAS SALADAS Salta A                                                              -25.7833    -64.5       4
AR 4126  BARADERO Salta A                                                                 -26.0833    -65.263     3
AR 4126  EL CUIBAL   Salta A                                                              -26.0833    -65.263     3
AR 4126  LA ASUNCION Salta A                                                              -26.0833    -65.263     3
AR 4126  MIRAFLORES (TALA, DPTO. CANDELARIA) Salta A                                      -26.0833    -65.263     3
AR 4141  TOLOMBON Salta A                                                                 -26.2       -65.9167    4
AR 4190  OJO DE AGUA (ROSARIO DE LA FRONTERA, DPTO. R.DE LA FRONTERA)   Salta A           -25.8       -65.0333    3
AR 4190  POTRERILLO (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA)   Salta A           -25.8       -65.0333    3

したがって、3番目の列から最後の列まで、左側は30番目のタブ、つまり88番目のスペースから始める必要があります。最後の3列の最初の文字は12個のスペースだけ離れています。

各行にはデータがあるので、最後の3つの列を別のファイルに切り取りようとしました。その後、元のファイルからすべてのスペースを削除してから、列形式で指定してみました。 3番目の列は私に問題を引き起こしています。

awk 'BEGIN{ OFS="\t"}{ print $1, $2, NR }' .allCountries.txt

AT      4873    Pehigen 34069
AT      4873    Hofberg 34070
AT      4873    Wiederhals      34071
AT      4873    Oberedt 34072
AT      4873    Oberegg 34073
AT      4873    Raitenberg      34074
AT      4873    Redltal 34075
AT      4873    Friedhalbing    34076
AT      4873    Unterhaselbach  34077
AT      4873    Redltal 34078
AT      4873    Erkaburgen      34079
AT      4873    Mayrhof 34080
AT      4873    Erdpries        34081
AT      4873    Grünbergsiedlung        34082
AT      4873    Brunnhölzl      34083
AT      4873    Seibrigen       34084
AT      4873    Kinast  34085
AT      4873    Stöckert        34086
AT      4873    Frankenburg     34087
AT      4873    Fischeredt      34088
AT      4873    Marigen 34089
AT      4873    Oberhaselbach   34090
AT      4873    Ottokönigen     34091
AT      4873    Fischigen       34092
AT      4873    Endriegl        34093

どんな助けでもいいでしょう。

答え1

これが可能だと思います。シンプルなシングルライナーとして、awk1.2mラインファイルに対して非常に迅速に実行する必要があります。あなたの例に基づいて130万行のダミーファイルを作成することで、4GB RAMとGNU Awk 4.0.2を搭載したネイティブCentOS 7 VMで24秒で完了することを確認しました。

StackExchangeから正確な応答を得るには、サンプル出力とともにサンプル入力をPastebinに公開できます。

$ awk '{printf "%s %-6s%-81s%-12s%-12s%s\n",$1,$2,gensub(/[0-9.-]* +[0-9.-]* +[0-9]$/,"","g",substr($0,10)),$(NF-2),$(NF-1),$NF}' inp | head
AD AD100 Canillo                                                                          42.5833     1.6667      6
AD AD200 Encamp                                                                           42.5333     1.6333      6
AD AD300 Ordino                                                                           42.6        1.55        6
AD AD400 La Massana                                                                       42.5667     1.4833      6
AD AD500 Andorra la Vella                                                                 42.5        1.5         6
AD AD600 Sant Julià de Lòria                                                              42.4667     1.5         6
AD AD700 Escaldes-Engordany                                                               42.5        1.5667      6
AR 3636  POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S))  Salta A                       -23.4933    -61.9267    3
AR 4123  LAS SALADAS Salta A                                                              -25.7833    -64.5       4
AR 4126  BARADERO Salta A                                                                 -26.0833    -65.263     3
$

オンラインでお試しください!

答え2

次のスクリプトを使用して目的を達成することができましたが、100万を超える行でどれだけうまく機能するかはわかりません。

#!/usr/local/bin/bash

tmp_dir="$(mktemp -d -t 'text.XXXXX' || mktemp -d 2>/dev/null)"
input=./input
output=./output
tmp_input1=${tmp_dir}/temp_input1.txt
tmp_input2=${tmp_dir}/temp_input2.txt
col1="${tmp_dir}/col1.txt"
col2="${tmp_dir}/col2.txt"
col3="${tmp_dir}/col3.txt"
col4="${tmp_dir}/col4.txt"
col5="${tmp_dir}/col5.txt"
col6="${tmp_dir}/col6.txt"

tr -s ' ' <"$input" > "$tmp_input1"

awk '{print $1}' "$tmp_input1" > "$col1"

awk '!($1="")' "$tmp_input1" > "$tmp_input2"

awk '{print $1}' "$tmp_input2" > "$col2"

awk '!($1="")' "$tmp_input2" > "$tmp_input1"

awk '{print $NF}' "$tmp_input1" > "$col6"

awk '!($NF="")' "$tmp_input1" > "$tmp_input2"

awk '{print $NF}' "$tmp_input2" > "$col5"

awk '!($NF="")' "$tmp_input2" > "$tmp_input1"

awk '{print $NF}' "$tmp_input1" > "$col4"

awk '!($NF="")' "$tmp_input1" > "$tmp_input2"

cat "$tmp_input2" > "$col3"

paste -d'\t' "$col1" "$col2" "$col3" "$col4" "$col5" "$col6"  | column -s$'\t' -t > "$output"

rm -r "$tmp_dir"

これにより、複数のtmpファイル(各列に1つずつ、元のファイルを変更するために2つ)が作成され、生の入力で処理され、3列だけが残るまで一度に1列ずつ削除されます。次に、すべてのtmpファイルをタブ区切り形式で貼り付け、column必要に応じて出力形式を指定します。

入力した内容に基づいて、次のことを行います。

$ ./script.sh
$ cat output
AD  AD100  Canillo                                                                42.5833   1.6667    6
AD  AD200  Encamp                                                                 42.5333   1.6333    6
AD  AD300  Ordino                                                                 42.6      1.55      6
AD  AD400  La Massana                                                             42.5667   1.4833    6
AD  AD500  Andorra la Vella                                                       42.5      1.5       6
AD  AD600  Sant Julià de Lòria                                                    42.4667   1.5       6
AD  AD700  Escaldes-Engordany                                                     42.5      1.5667    6
AR  3636   POZO CERCADO (EL CHORRO (F), DPTO. RIVADAVIA (S)) Salta A              -23.4933  -61.9267  3
AR  4123   LAS SALADAS Salta A                                                    -25.7833  -64.5     4
AR  4126   BARADERO Salta A                                                       -26.0833  -65.263   3
AR  4126   EL CUIBAL Salta A                                                      -26.0833  -65.263   3
AR  4126   LA ASUNCION Salta A                                                    -26.0833  -65.263   3
AR  4126   MIRAFLORES (TALA, DPTO. CANDELARIA) Salta A                            -26.0833  -65.263   3
AR  4141   TOLOMBON Salta A                                                       -26.2     -65.9167  4
AR  4141   QUISCA GRANDE Salta A                                                  -26.4367  -65.97    3
AR  4141   LA CIENEGUITA Salta A                                                  -26.4367  -65.97    3
AR  4141   MACHO RASTROJO Salta A                                                 -26.4367  -65.97    3
AR  4190   ROSARIO DE LA FRONTERA Salta A                                         -25.8     -64.9667  4
AR  4190   OVANDO Salta A                                                         -25.8     -65.1     4
AR  4190   SAN ESTEBAN Salta A                                                    -25.8     -65.0333  3
AR  4190   LA BANDA (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA) Salta A     -25.8     -65.0333  3
AR  4190   LA MATILDE Salta A                                                     -25.8     -65.0333  3
AR  4190   LAS PIEDRITAS Salta A                                                  -25.8     -65.0333  3
AR  4190   LOS POCITOS Salta A                                                    -25.8     -65.0333  3
AR  4190   OJO DE AGUA (ROSARIO DE LA FRONTERA, DPTO. R.DE LA FRONTERA) Salta A   -25.8     -65.0333  3
AR  4190   POTRERILLO (R. DE LA FRONTERA, DPTO. ROSARIO DE LA FRONTERA) Salta A   -25.8     -65.0333  3

関連情報