1

私は現在、csv ファイルを処理するスクリプトに取り組んでおり、途中でそれらの特定の側面を修正しています。それが行うことの 1 つは、必要に応じて正しい時刻形式です。2 種類の変換が行われます。

 xx:xx:xx to PTxxHxxMxxS
 10:03:45 to PT10H03M45S

プロセスを高速化するためにsedまたはawkを使用してそれを行う方法を見つけようとしていますが、次の方法を使用してこれを行うことができました(以下を参照)。実際の変換プロセスに加えて、行われた変更のカウントも保持したいと思います (つまり、4 回の値が変換され、カウンターが 4 にインクリメントされるとします)。これは、if で簡単に行うことができました。 sed/awk を使用してそれを行うことについてはあまり知りませんが、以下のステートメント (表示されていません)。

 istimef=$( echo "$Sfcpp6" | grep ".*:.*:.*" )
                    if [ "$istimef" != "" ]; then
                            hs=$( echo "$Sfcpp6" | cut -d ':' -f 1 )
                            mn=$( echo "$Sfcpp6" | cut -d ':' -f 2 )
                            sc=$( echo "$Sfcpp6" | cut -d ':' -f 3 )
                            Sfcpp6=$( echo "PT"$hs"H"$mn"M"$sc"S" )
                            echo "$Sfcp6"
                    fi

これは基本的に時間値がそこにあるかどうかをチェックし、変換を実行します。

4

4 に答える 4

2

このタスクに必要なプロセスとサブシェルの数は驚くべきものです。人々の創意工夫と創造性にはいつも驚かされます。10 個のサブシェルと 4 個のプロセス スポーンを数えました。

ほら、1つのプロセスを生成せず、サブシェルをまったく使用せずに、まったく同じことを達成できます。ここでは高速化について説明します。

最初のタスクは、フォームの文字列を与えられ、それを可能な限り効率的xx:yy:zzに変換します (見てください、たった 1 つのコマンドで! ビルトインで! いいえ!):PTxxHyyMzzSsed

$ string='12:34:56'
$ printf -v transformed 'PT%sH%sM%sS' ${string//:/ }
$ # Done! Don't believe me?
$ echo "$transformed"
PT12H34M56S

さて、これを行う前に、おそらく文字列が の形式であるかどうかを確認したいと思うでしょうxx:yy:zz。そのためにやめなさいgrep。次のようにテストしてください:

if [[ "$string" = *:*:* ]]; then
    echo "ok"
else
    echo "not ok"
fi

したがって、あなたが私たちに示したスクリプトの部分は、次のようにはるかに効率的になります。

if [[ "$Sfcpp6" = *:*:* ]]; then
    printf -v Sfcp6 'PT%sH%sM%sS' ${Sfcpp6//:/ }
    echo "$Sfcp6"
fi

合計: 0 サブシェル、生成された 0 プロセス。

または、変換された文字列をエコーすることだけが目的の場合:

if [[ "$Sfcpp6" = *:*:* ]]; then
    printf 'PT%sH%sM%sS\n' ${Sfcpp6//:/ }
fi
于 2012-12-01T20:53:25.230 に答える
0

置換された行を数えたい場合:

perl -pe '
    END{print "count=$count\n"}
    s/(\d{2}):(\d{2}):(\d{2})/PT$1H$2M$3S/ && $count++
' file.txt
于 2012-12-01T20:52:36.403 に答える
0

@choroba によって投稿されたこの sed ソリューションに相当する GNU awk :

sed 's/\([0-9][0-9]\):\([0-9][0-9]\):\([0-9][0-9]\)/PT\1H\2M\3S/'

非常に似ています:

awk '{print gensub(/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])/,"PT\\1H\\2M\\3S","")}'

ただし、 awk ソリューションを簡単に変更して、「行った変更を sed にカウントさせることは可能でしょうか?」という質問に対処することができます。

awk '{orig=$0; $0=gensub(/([0-9][0-9]):([0-9][0-9]):([0-9][0-9])/,"PT\\1H\\2M\\3S",""); print} $0 != orig{count++} END{printf "%d changes made.\n",count}'

sed ソリューションはできませんが。

于 2012-12-02T14:48:32.637 に答える