2011-12-25 19 views
2

私はMakefileです。変数はversionbuildです(これらは唯一の変数ではなく、異なる順序で定義できます)。 sedだけを使用して、値を単一のバージョン文字列に結合したいと思います。sedを使用して1行に複数の一致を出力する

sed -n -e '/=/{s/version.*=\(.*\)/\1\./p;s/build.*=\(\d*\)*/\1/p}' Makefile 

が、両方の値が改行で区切られています。

は、これまでのところ私は持っています。

 
0.8.2. 
1 

私がしたい:

0.8.2.1

を私はNを試してみましたが、この中でそれを使用する方法を見つけ出すことができませんでした上記の次の出力が生成され徴候

なぜ制限がありますか?私はそれを学びたいと思う、それは私のための最善の方法です。

スタンドアロンサンプル:すべて同じ考え方に基づいており、次の

sed -n -e '/=/ {s/version.*=\(.*\)/\1\./p;s/build.*=\(\d*\)*/\1/p}' <<EOF 
foo=1 
version=0.8.2 
bar=2 
build=1 
bam=bug-AWWK 
EOF 

答えて

4

:バージョンを保存し、ビルド番号、入力の最後にそれらを印刷。

sedには、現在の行の値で始まるパターンスペースと、処理中の値を保存するための保存スペースがあります。バージョンは、ホールドスペースの値の前に追加する必要があります。これは、ホールドスペースをGというパターンスペースに追加することで実現できます。ビルドは、Hで実行できるホールドスペースに追加する必要があります。 Hが作成する改行を削除するには、保留スペースをパターンスペースに戻します。どちらの場合も、GHで作成された改行はs///で削除され、次にhで保留スペースに戻ります。入力の最後は$アドレスで表され、保持スペースがパターンスペースに戻されて印刷されます。表示するのが短くなります:

sed -n -e '/^version.*=/ {s/[^=]*=//; G; s/\n//; h; } ' \ 
     -e '/^build.*=/ { s/[^=]*=//; H; g; s/\n/./; h; } ' \ 
     -e '$ { g; P; }' 

これは文字列の最後に改行を生成しますが、うまくいけば問題はありません。

ユーティリティのawkファミリは変数をサポートしているため、タスクがより簡単になります。それらには特殊な変数OFS、出力フィールドセパレータ、出力レコードセパレータORSがあります。 awkのprintは、各引数の間にOFSを出力し、最後にORSを出力します。特別なパターンENDは、入力の終了後に一致します。

awk -v OFS=. -v ORS='' \ 
    '/^version.*=/ {sub(/^[^=]*=/, ""); version=$0;} \ 
    /^build.*=/ {sub(/^[^=]*=/, ""); build=$0;} \ 
    END {print version, build;}' 

あなたが最後のドットを気にしないと、バージョンの順序の特定することができ、メイクファイル内の行を構築する場合:

awk -v ORS=. '/(version|build).*=/ { sub(/^[^=]*=/, ""); print; } ' 

の言語の表現に上向き継続はperlのです。 perlのENDにはawkと同様の機能があり、プロセスの最後に実行されるブロックをマークします。ハッシュを使用して完全なバージョン番号の部分を保存し、行を一致させてバージョンとビルドを保存して1行にまとめることができます。

perl -n -e '$ver{$1} = $2 if /^(version|build)[^=]*=(.*)/; \ 
      END {$,="."; print @ver{"version","build"}};' 

興味深い練習のためにsedを使用していますが、エクササイズの価値は自分自身を強化することです。他の人に向ける必要がある場合は、solve the problemにどのように挑戦しているかに集中するのではなく、推奨される方法を見つけ出す方がよいでしょう。あなたはもっと学ぶでしょう。

+1

「 – Kent

+0

@Kentのみのsedを使って」言及OP:AWK何、みじん切り肝臓時には質問者はそれが教育目的のためだとしても、を求めたものよりももっと良いものがあるのを誰かがを求めた場合は?。ソケットレンチが手に近づいたときに六角ボルトを取り外すためにバイスグリップを使用すると、ソケットレンチを手に渡すことができますが、それはできません、それほど良いものではありません。文字列とそれを最後にのみ出力しますが、awkは一致する行ごとに出力します。出力文字列が短いため、例との違いはほとんどありませんが、常にそうであるとは限りません。 – outis

+1

if Iこの問題があった、私の最初の試みはawkすぎるだろう。ほとんどのケースでは、awkはsedよりはるかに柔軟です。 (個人的な意見)。 OPは答えの範囲を狭める。あなたからのawkソリューションのために、btw。私はテストしなかった。私は最後に余分なドット( "。")があるだろうと思う。一致したすべての行について\\ 1と "。"を出力するからです。最後に。 ORSと\\ 1 "ドットを繰り返すことがあります。 – Kent

1

は、あなたのメイクファイルでこれを試してください:あなたの例のテキストを

sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' makefile 

テスト:ケース・ビルドで

kent$ sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' <<<"foo=1 
dquote> version=0.8.2 
dquote> bar=2 
dquote> build=1 
dquote> bam=bug-AWWK 
dquote> EOF" 
0.8.2.1 

バージョンの前に示しています

kent$ sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' <<<"foo=1 
bar=2 
build=1 
bam=bug-AWWK 
version=100.8.2" 
1.100.8.2 
+1

あなたが '/^version \ |^build /'を使うなら '-r'の依存関係の' – SiegeX

0

これはあなたのために働くかもしれません。

cat makefile | 
sed '/^\(version\|build\)/H;${x;s/^\(\nbuild.*\)\(\n.*\)/\2\1/;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d' 
0.8.2.1 
tac makefile | 
sed '/^\(version\|build\)/H;${x;s/^\(\nbuild.*\)\(\n.*\)/\2\1/;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d' 
0.8.2.1 

バージョンは、その後、ビルドの前または後に来る場合、あなたの気にされていない場合:

sed '/^\(version\|build\)/H;${x;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d' 
0.8.2.1 

ソリューションを@outis読んでたので、ここでは地味鑑賞するために彼の解決策の改善バージョンは次のとおりです。

sed '/^version=/{s///;G;h};/^build=/{s//./;H};${g;s/\n//gp};d' makefile 
0

あなたがawkに開いている場合、ここに別の解決策があります。 sedコードを入力することによって引き起こされる指のけいれんを防ぎます。 No offence to the brilliant solutions offered by potong and kent;)

awk -F"=" ' 
BEGIN{i=1} 
(/version|build/){a[i]=$NF;i++} 
END{for(i=1;i<=2;i++) if(i==1) {printf a[i]"."} else printf a[i]}' Makefile 
関連する問題