入力行に対する for ループ

入力行に対する for ループ

このような行がたくさんあるファイルがあります

/item/pubDate=日曜日、2014年2月23日 00:55:04 +010

これを実行すると

echo "/item/pubDate=Sun, 23 Feb 2014 00:55:04 +010" | grep -Po "(?<=\=).*"

Sun, 23 Feb 2014 00:55:04 +010

正しい日付を取得しました (すべて 1 行で)。今度は、xml ファイル内の多数の日付でこれを試してみたいと思います。これを使用しても問題ありません。

xml2 < date_list | egrep "pubDate" | grep -Po "(?<=\=).*"
Fri, 22 Jan 2016 17:56:29 +0100
Sun, 13 Dec 2015 18:33:02 +0100
Wed, 18 Nov 2015 15:27:43 +0100
...

しかし、今私はbashプログラムで日付を使いたいのですが、この出力が得られます

for fecha in $(xml2 < podcast | egrep "pubDate" | grep -Po "(?<=\=).*"); do echo $fecha; done
    Fri,
    22
    Jan
    2016
    17:56:29
    +0100
    Sun,
    13
    Dec
    2015
    18:33:02
    +0100
    Wed,
    18
    Nov
    2015
    15:27:43
    +0100

最初の例と 2 番目の例のように、日付を 1 行 (変数 fecha) で出力したいのですが、方法がわかりません。

答え1

代わりに次のようにしてください:

while IFS= read -r fecha; do
    echo $fecha
done < <(xml2 < podcast | egrep "pubDate" | grep -Po "(?<=\=).*")

Bash は、ループする「単語」を内部フィールド区切り文字 ( $IFS) の文字で区切ります。コマンドIFSの実行中は何も設定しないことで、この動作を一時的に無効にすることができますread。上記のパターンは、常に行ごとにループします。

<(command)コマンドの出力を実際のファイルのように見せ、それをreadループにリダイレクトします。

$ while IFS= read -r line; do echo $line; done < <(cat ./test.input)
Fri, 22 Jan 2016 17:56:29 +0100
Sun, 13 Dec 2015 18:33:02 +0100
Wed, 18 Nov 2015 15:27:43 +0100

答え2

xml2 < date_list | egrep "pubDate" | grep -Po "(?<=\=).*" \
| while read L
  do
    echo $L
  done

読む行ごとに分割し、要求されない限り単語を分割しません。 :-)

しかし、正規表現を使用して XML に取り組むことは、銃撃戦にナイフを持っていくようなものです。上記のパイプラインが見逃したり、誤ってキャプチャしたりする有効な XML を構築することは非常に簡単です。

XML を多く扱う場合は、SAX パーサーに慣れておく必要があります。

関連情報