AWK:FSの現場作業と「チェーン」作業を一緒に「変更」

AWK:FSの現場作業と「チェーン」作業を一緒に「変更」

Wikipediaテーブルから情報を取得するためにMediaWiki APIページのデータをawk解析するスクリプトを作成しています。JSONこれは私が使用している例であり、awkにパイプされています。

私の意図は次のとおりです

  • \nテキスト項目を実際の改行文字に置き換える
  • 一部の項目を区切る単一の垂直バーの前にある一部の項目と、すべての項目を囲む二重角かっこを削除します。
  • すべての二重垂直バーを||単一の垂直バーに置き換えます。フィールド区切り記号として使用するには
  • 各行の先頭にある前の垂直バーを削除します。
  • 指定されたフィールドを印刷し、空白行と先行スペースを削除します。

今の問題はこれをうまく実装しましたが、awk他のインスタンスをパイプして非常に醜い方法で実装したということです。これが私が今まで得たものです:

curl -s 'https://en.wikipedia.org/w/api.php?action=parse&prop=sections&page=List_of_islands_of_Spain&section=1&prop=wikitext&format=json' |\
    awk 'BEGIN { FS = "|" }\
    gsub (/\\n/, "\n") gsub (/\[\[[^\|]*\||\]\]/, "")\
    gsub (/\|\|/, "|")' |\ # Sub. "\n" for line-break, remove "[[" and "]]", substitute "||" for "|"
    awk 'gsub (/^\|/, "")' |\ # Remove leading "|"
    awk 'BEGIN { FS = "|" } {print $5}' |\ # Print 5th field
    awk '{gsub (/^[ \t]*/, "")} NF' # Remove any leading whitespace and delete empty lines

私は過去3つのケースで、およびを使用できることを知っていますが、sedこのスクリプトを使用してスキルを開発しようとしています。cutawk

私が気づいたことの1つは、出力が変更されたにもかかわらず、最初のインスタンスで文字列操作が行われたことです。NR または NF は変更しません。。これが私が経験している問題の原因だと思いますが、どのように解決すべきかわかりません。

これが私が知りたいことです:

これらすべてのタスクを単一のawkインスタンスに「接続」できますか?内部的には、これらの作業の間に「パイプライン」のようなものがありますかawk

お答えいただきありがとうございます。

ベストアンサー1

JSONを解析するためにawkを使用することの知恵については議論しません(gawks JSONライブラリを使用しない限り)。しかし、awk呼び出しのシェルパイプラインを変換する方法について説明します。

awk 'BEGIN { FS = "|" }\
gsub (/\\n/, "\n") gsub (/\[\[[^\|]*\||\]\]/, "")\
gsub (/\|\|/, "|")' |\ # Sub. "\n" for line-break, remove "[[" and "]]", substitute "||" for "|"
awk 'gsub (/^\|/, "")' |\ # Remove leading "|"
awk 'BEGIN { FS = "|" } {print $5}' |\ # Print 5th field
awk '{gsub (/^[ \t]*/, "")} NF' # Remove any leading whitespace and delete empty lines

単一のawkコマンドで。

awkは、構文や意味がシェルとは異なるCに似たプログラミング言語です。 CプログラムでCステートメントを互いにパイプする方法については考えず、awkプログラムでもそうしません。

この試み:

$ cat tst.awk
BEGIN { FS = "|" }
{
    gsub(/(\[\[[^|]*\|)|(]])/, "")
    gsub(/\|\|/, FS)
    split($0,lines,/\\n/)
    for (i=1; i in lines; i++) {
        $0 = lines[i]
        sub(/^[[:space:]]+/, "", $6)
        if ( $6 !~ /^$/ ) {
            print $6
        }
    }
}

curl -s 'https://en.wikipedia.org/w/api.php?action=parse&prop=sections&page=List_of_islands_of_Spain&section=1&prop=wikitext&format=json' |
awk -f tst.awk

Province
Isla de \u00cdzaro
Garraitz
Santa Clara
Aqueche
Txatxarramendi
Villano
Montehano
Santa Marina o Los Jorganes
Pedrosa
Virgen del Mar
Castril, Am\u00edo o M\u00edo, Las Lastras de Pech\u00f3n
La Pasiega o Solita
La Torre
Ratones o Marnay
Neptuno Ni\u00f1o
Ori\u00f1\u00f3n
Castro
Cuarezo
Llera
\u00c1guila
Suaces
Garfanta
Deva
Pantorgas
Isla Herbosa
Isla del Carmen
Illa de Arousa
Ons
La Toja Peque\u00f1a
Ansar\u00f3n
Guidoiro Areoso
A Creba
Lobeiras
Centoleiras
Beiro
Farall\u00f3ns
Guidoiro Pedregoso
Malveiras
Isla de Santa Cruz
Isla Herbosa
San Clemente
San Vicente
San Ant\u00f3n (Pontevedra)
San Ant\u00f3n (La Coru\u00f1a)
Pancha
Gavoteira
Isla de Santa Catalina
Isla Canela
Isla de Salt\u00e9s
Las Palomas
Trocadero
Sancti Petri
San Andr\u00e9s
Terreros
Isla Negra
Albor\u00e1n
San Sebasti\u00e1n
Piedra del Hombre
Isla Mayor
Rondella
Las Palomas
Isla de Tabarca
Benidorm
Portichol
Descubridor
Medas
Port Lligat
Encalladora
Cabrera
Isla del Rey

RSGNU awkを使用すると、sで入力自動分割を設定でき、スクリプト内でsを分割する必要が\\nないことに注意する価値があります。\\n

$ printf 'foo\\\\nbar\n'
foo\\nbar

$ printf 'foo\\\\nbar\n' | awk '{split($0,lines,/\\\\n/); for (i=1; i in lines; i++) print i, lines[i]}'
1 foo
2 bar

$ printf 'foo\\\\nbar\n' | awk 'BEGIN{RS="[\\\\]{2}n|\n"} {print NR, $0}'
1 foo
2 bar

おすすめ記事