コミュニティ/Netnews 斜め読み

トップ 差分 一覧 Farm ソース 検索 ヘルプ RSS ログイン

comp.lang.awk

  • Netnews の comp.lang.awk を適当に日本語訳して抜粋してあります。(本当に適当です)
  • 書き込んだ人の名前の部分はオリジナルの投稿者の名前に変更させていただきましたが、時間までは変更していません。詳しくは、comp.lang.awk を購読していただくか、Google グループの comp.lang.awk などで確認してください。
  • 件数が増えてきたら古いものから順に過去ログに移動します。過去ログは [complangawk] から参照できます。

最近のタイトル一覧

[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ]

comp.lang.awk

お名前
件名
本文

awk vs expect/tcl - born2Script (2005年09月24日 00時55分06秒)

TCL のような文法ではなく、自動インタラクティブツールとして Expect に興味があります。

awk で Expect の send/expect を実装できますか?それともすでに実装されていますか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/30861abd3ad434c2/b595e3a6c5711f67?hl=ja#b595e3a6c5711f67


  • expect のスクリプトを作成するのに autoexpect を使ったのではダメですか? - John L (2005年09月24日 00時56分29秒)

{{comment}}

Need To Extract Data From Files Within Awk Script - Vadmin (2005年09月23日 03時43分27秒)

以下のようなファイルがあります。

/systemdata/cluster1/091805/serial.number.091805
             ^^$1^^  ^date^               ^date^

ここで、

serial_num = "cat /systemdata/'$1'/'date'/serial.number.'date'";

と書いていて、

print "  <td>", (system(serial_num)), "</td>";

としています。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/9bc7723add58ed3f/da5c51e2dc023ca3?hl=ja#da5c51e2dc023ca3


  • 以下のようなことを行いたいのでしょうか? - Ed Morton (2005年09月23日 03時45分17秒)

こんな感じで今は作られています。

$1="cluster1"   # in shell
date="091805"   # in shell

awk '{
serial_num = "cat /systemdata/'$1'/'date'/serial.number.'date'"
print "  <td>", (system(serial_num)), "</td>"
}'                                                                                           

でも、この状態では cat が正常に動作していないのではないでしょうか?

$1="cluster1"   # in shell
date="091805"   # in shell

awk '{
serial_num = "cat /systemdata/" dir "/" date "/serial.number." date
print "  <td>", (system(serial_num)), "</td>"
}' dir="$1" date="$date"                                                                     

のようにしてみてください。

  • 以下のようにしてできました。 - William James (2005年09月23日 03時47分29秒)

以下を消します。

$0 && NR==1{print "<tr BGCOLOR=\"#A6A6A6\">";
    print "  <td>", $1, "</td>";
    print "  <td>", $2, "</td>";
    print "  <td>", $3, "</td>";
    print "  <td>", $4, "</td>";
    print "  <td>", $5, "</td>";
    print "  <td>", $6, "</td>";
    print "  <td>", $7, "</td>";
    print "  <td>", $8, "</td>";
    print "  <td>", $9, "</td>";
    print "</tr>";
   }

そして

$0 && NR==1 { print "<tr BGCOLOR=\"#A6A6A6\">"
    for (i=1; i<=9; i++)
      print "  <td>", $i, "</td>"
    print "</tr>"
   }

で置き換えます。

  • date は以下のようになります。 - Vadmin (2005年09月24日 00時36分57秒)
DATE="`/bin/date +%m%d%y`"
  • 以下のように試してみました。 - Vadmin (2005年09月24日 00時38分31秒)
DATE="`/bin/date +%m%d%y`"
BEGIN { FS = ",";
serial_num = "cat /systemdata/'$1'/$DATE/serial.number.$DATE";
print "  <td>", (system(serial_num)), "</td>";
  • 次のようにしなければいけません。 - Ed Morton (2005年09月24日 00時40分11秒)
  • BEGIN からコードを移動させて
  • シングルクォートをダブルクォートにします。
BEGIN { FS = "," }
{ serial_num = "cat /systemdata/"$1"/$DATE/serial.number.$DATE";

また、DATE の問題は、shell 変数ベースのものを awk 変数に与える必要があります。

DATE="`/bin/date +%m%d%y`"
awk 'BEGIN { FS = "," }
{ serial_num = "cat /systemdata/" $1 "/" date "/serial.number." date;
    .....
}' date="$DATE" <inputfile>                                                                  

ただし、gawk なら DATE コマンドは不要です。

  • 以下のようにしましたが、DATE コマンドがうまく動作しません。 - Vadmin (2005年09月24日 00時45分08秒)
DATE="`/bin/date +%m%d%y`"
{ serial_num = "cat /systemdata/"$1"/"date"/serial.number."date;
   } date="$DATE"                                                                            
  • gawk を使っているのであれば、以下のようにします。 - Ed Morton (2005年09月24日 00時47分27秒)

strftime() 関数で時間は取得できます。

$ gawk 'BEGIN{print strftime("%m%d%y")}'
092305

そうすることで、以下のように書けます。

gawk 'BEGIN{ date=strftime("%m%d%y") }
{ serial_num = "cat /systemdata/"$1"/"date"/serial.number."date
    ....
}'                                                                                           
  • 以下のようにしてみてください。 - William James (2005年09月24日 00時51分15秒)
#!/usr/bin/awk -f

BEGIN { FS = ","

  ##
  ##
  ##  Get today's date.
  ##
  ##
  date = strftime( "%m%d%y" )

        print "<html>"
        print "<head></head>"
        print "<body>"
        print "<center><h3>Updated Machine Listing</h3></center>"
        print "<center>"
        print strftime("Updated: %A, %B %d, %Y, %R <br>")
        print "<table>"
        print "<table BORDER=1>"
}

$0 && NR==1 { print "<tr BGCOLOR=\"#A6A6A6\">"
    for (i=1; i<=9; i++)
      print "  <td>", $i, "</td>"
    print "</tr>"
}


$0 && NR>1 {
   color=((NR%2)==0) ? "#E6E6E6" : "#FFFFFF"
   ping_command = "ping -c 2 " $1 ">/dev/null"
   status=(system(ping_command)) ? "INACTIVE" : "ACTIVE"


   ##
   ##  Read serial-number from correct file.
   ##

   filename = "/systemdata/" $1 "/" date "/serial.number." date
   if ( (getline serial_num < filename) < 1)
   {  print "Error while reading", filename >"/dev/stderr"
      exit(1)
   }
   close( filename )

   printf ("<tr BGCOLOR=%s>\n", color)
   print "  <td><a href=\"telnet://"$1"\">", $1, "</a></td>"
   print "  <td><a href=\"telnet://"$2"\">", $2, "</a></td>"
   print "  <td>", $3, "</td>"
   print "  <td>", $4, "</td>"
   print "  <td>", $5, "</td>"
   print "  <td>", serial_num, "</td>"
   print "  <td>", $7, "</td>"
   print "  <td>", status, "</td>"
   print "  <td><a href=\"telnet://"$9"\">", $9, "</a></td>"
   print "</tr>"
}

END {   print "</table>"
        print "</center>"
        print "</body>"
        print "</html>" }
  • 以下のように変更してください。 - William James (2005年09月24日 01時40分03秒)
  ##
  ##  Read serial-number from correct file.
  ##

  filename = "/systemdata/" $1 "/" date "/serial.number." date
  if ( (getline serial_num < filename) < 1)
  {  print "Error while reading", filename >"/dev/stderr"
     exit(1)
  }
  close( filename )

を以下のように変更。

  ##
  ##  Read serial-number from correct file.
  ##

  filename = "/systemdata/" $1 "/" date "/serial.number." date
  if ( (getline serial_num < filename) < 1)
  {  print "Error while reading", filename >"/dev/stderr"
     serial_num = "X"
  }
  close( filename )
  • 以下のようにすることができます。 - Ed Morton (2005年09月26日 00時52分24秒)
   printf ("<tr BGCOLOR=%s>\n", color)
   print "  <td><a href=\"telnet://"$1"\">", $1, "</a></td>"
   print "  <td><a href=\"telnet://"$2"\">", $2, "</a></td>"
   print "  <td>", $3, "</td>"
   print "  <td>", $4, "</td>"
   print "  <td>", $5, "</td>"
   print "  <td>", serial_num, "</td>"
   print "  <td>", $7, "</td>"
   print "  <td>", status, "</td>"
   print "  <td><a href=\"telnet://"$9"\">", $9, "</a></td>"
   print "</tr>"

という部分は、

   BEGIN{td="  <td> %s </td>\n";
   tdR="  <td><a href=\"telnet://%s\"> %s </a></td>\n"}
   printf "<tr BGCOLOR=%s>\n", color
   printf tdR, $1, $1
   printf tdR, $2, $2
   printf td, $3
   printf td, $4
   printf td, $5
   printf td, serial_num
   printf td, $7
   printf td, status
   printf tdR, $9, $9
   print "</tr>"

とするか、

   function prttd(txt) { printf "  <td> %s </td>\n", txt }
   function prttdR(txt) { printf "  <td><a href=\"telnet://%s\"> %s
</a></td>\n", txt, txt }
   printf "<tr BGCOLOR=%s>\n", color    prttdR($1)
   prttdR($2)
   prttd($3)
   prttd($4)
   prttd($5)
   prttd(serial_num)    prttd($7)
   prttd(status)    prttdR($9)
   print "</tr>"

とすることで、簡単にできます。{{comment}}


  • つくづく Ed さんは親切だと思いますが、awk といえ、ある程度ドキュメントを読まないとこういう問題が発生するんですかね。 - hi_saito (2005年09月24日 00時46分39秒)

Unable To Read Input From Files - Vadmin (2005年09月23日 03時32分27秒)

以下のようなファイル名があります。

/systemdata/cluster1/091805/
            ^^^^^^^^

また、別のものは以下のような名前です

/systemdata/cluster2/091805/
            ^^^^^^^^

つまり、別のホスト名です。

そして、実際に日々の cron で置かれるデータは以下のようなものです。

/systemdata/cluster1/091805/serial.number.091805
             ^^$1^^  ^date^               ^date^

そういうファイルです。

awk のスクリプトは以下のようなものです。

#!/usr/bin/awk -f
#
#  I couldn't get functions to work, here is an example...
#
# function help()
#              {
#           echo "Usage: "gen-hosts.awk"  <InputFile>";
#           exit(0);
#        }

BEGIN { FS = ",";
        print "<html>";
        print "<head></head>";
        print "<body>";
        print "<center><h3>Updated Machine Listing</h3></center>";
        print "<center>";
        print strftime("Updated: %A, %B %d, %Y, %R <br>");
        print "<table>";
        print "<table BORDER=1>"; }


$0 && NR==1{print "<tr BGCOLOR=\"#A6A6A6\">";
    print "  <td>", $1, "</td>";
    print "  <td>", $2, "</td>";
    print "  <td>", $3, "</td>";
    print "  <td>", $4, "</td>";
    print "  <td>", $5, "</td>";
    print "  <td>", $6, "</td>";
    print "  <td>", $7, "</td>";
    print "  <td>", $8, "</td>";
    print "  <td>", $9, "</td>";
    print "</tr>";
   }

$0 && NR>1 { color=((NR%2)==0) ? "#E6E6E6" : "#FFFFFF";
         ping_command = "ping -c 2 " $1 ">/dev/null"
         status=(system(ping_command)) ? "INACTIVE" : "ACTIVE";

         serial_num = "cat
/systemdata/'$1'/'date'/serial.number.'date'";

   printf ("<tr BGCOLOR=%s>\n", color);
   print "  <td><a href=\"telnet://"$1"\">", $1, "</a></td>";
   print "  <td><a href=\"telnet://"$2"\">", $2, "</a></td>";
   print "  <td>", $3, "</td>";
   print "  <td>", $4, "</td>";
   print "  <td>", $5, "</td>";
   print "  <td>", (system(serial_num)), "</td>";
   print "  <td>", $7, "</td>";
   print "  <td>", status, "</td>";
   print "  <td><a href=\"telnet://"$9"\">", $9, "</a></td>";
   print "</tr>";
  }

END {   print "</table>";
        print "</center>";
        print "</body>";
        print "</html>"}

出力は以下のとおりです。

<html>
<head></head>
<body>
<center><h3>Updated Machine Listing</h3></center>
<center>
Updated: Thursday, September 22, 2005, 09:37 <br>
<table>
<table BORDER=1>
<tr BGCOLOR="#A6A6A6">
  <td> Hostname </td>
  <td> Aliases </td>
  <td> Purpose </td>
  <td> Architecture </td>
  <td> OS </td>
  <td> System Serial Number </td>
  <td> Description </td>
  <td> Status </td>
  <td> IP_Address </td>
</tr>
<tr BGCOLOR=#E6E6E6>
  <td><a href="telnet://cluster1"> cluster1 </a></td>
  <td><a href="telnet://cluster"> cluster </a></td>
  <td> Devel </td>
  <td> Intel </td>
  <td> RH Linux 2.6 </td>
cat: cannot open /systemdata/'$1'/'date'/serial.number.'date'
  <td> 2 </td>
  <td> Test Box1 </td>
  <td> ACTIVE </td>
  <td><a href="telnet://192.168.1.1"> 192.168.1.1 </a></td>
</tr>
<tr BGCOLOR=#FFFFFF>
  <td><a href="telnet://cluster2"> cluster2 </a></td>
  <td><a href="telnet://cluster"> cluster </a></td>
  <td> Production </td>
  <td> Sparc </td>
  <td> SunOS 2.8 </td>
cat: cannot open /systemdata/'$1'/'date'/serial.number.'date'
  <td> 2 </td>
  <td> Test Box2 </td>
  <td> ACTIVE </td>
  <td><a href="telnet://192.168.1.2"> 192.168.1.2 </a></td>
</tr>
</table>
</center>
</body>
</html>

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/13f6f32a014e2658/7ce4638aefd649c2?hl=ja#7ce4638aefd649c2


  • 読むのが疲れるから、もっと短い例はありませんか? - Ed Morton (2005年09月23日 03時36分44秒)
  • でもこれが全てなんです。 - Vadmin (2005年09月23日 03時38分27秒)
  • まず、function 関数では括弧は最初の行になければいけません。 - Patrick TJ McPhe? (2005年09月24日 00時16分50秒)
 function help() {
         echo "Usage: "gen-hosts.awk"  <InputFile>";
         exit(0);
      }                                                                                     

次に、使っている連接は、

serial_num = "cat /systemdata/'$1'/'date'/serial.number.'date'";

ではなく、

serial_num = "cat /systemdata/" $1 "/" date "/serial.number." date

でなければいけません。awk は shell のように変数展開しません。

  • mawk, gawk では function の括弧は最初の行に書く必要はありません。問題は echo を使っているところだと思います。 - William James (2005年09月24日 00時19分54秒)
function help()                                                                              
{
  print "Usage: \"gen-hosts.awk\"  <InputFile>"
    exit(0)
}                                                                                            
BEGIN { help() }

{{comment}}


  • 確かに何が言いたいのか、最初は全然分かりませんでした。 - hi_saito (2005年09月23日 03時37分14秒)

splitting field seperator with 〔〕 - Gernot Frisch (2005年09月23日 03時23分52秒)

C++ のファイルを解析して、変数名と思われるものを抜き出そうとしています。a-z, A-Z, _ で始まり、a-Z, 0-9, _ しか含みません。FS を

FS="[(){},; ^\t-+*/<>!~?:%&=]";

とした時に [ と ] はどうすればいいのでしょうか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/12d59b9244993f06/977c3f4bdf903dfc?hl=ja#977c3f4bdf903dfc


  • 以下のようにすれば良いのではないでしょうか? - Ed Morton (2005年09月23日 03時24分23秒)
FS="[](){},; ^\t-+*/<>!~?:%&=[]"

たとえば、以下のようなものではどうですか?

FS="[^[:alnum:]_]*"

アルファベットか数字かアンダーバーで始まるものに該当します。{{comment}}

is this possible with gawk - bryan.hepworth (2005年09月22日 01時17分47秒)

Outlook アドレスブックを spamassassin の ham リストに自動で加えようとしています。

gawk -F"\t"'BEGIN{print"#Autogenerated
whitelist\n"}{print"whitelist_from ",$58\n}' <
outlooktabbedtextfile.txt > whitelistforspamassassin

メールアドレスがないコンタクトリストのエントリーだとうまくいきます。エントリーを書く前にテストすることは可能ですか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/061a690ff0d81cf2/0e296229a8db36c0?hl=ja#0e296229a8db36c0


  • 以下のようなテストをしてみてください。 - Ed Morton (2005年09月23日 02時58分46秒)
if ($58) print "not blank"; else print "blank"
  • 少し変えてみました。 - bryan.hepworth (2005年09月23日 02時59分24秒)
gawk -F"\t"'BEGIN{print"#Autogenerated Whitelist\n"}{if
($58)print"whitelist_from",$58; else print""}' <inputfile

でも、最後の else 文で何もせずに次の行に行っています。

  • 間違っていました。 - bryan.hepworth (2005年09月23日 03時02分16秒)
gawk -F"\t"'BEGIN{print"#Autogenerated Whitelist\n"}{if
($58)print"whitelist_from",$58; else next}' <inputfile
  • ヒントを出しましょう。 - Ed Morton (2005年09月23日 03時03分09秒)

何もしないということを else 文でやりたい場合には、else を使ってはいけません。そうすると以下のようになります。

gawk -F"\t"'BEGIN{print"#Autogenerated Whitelist\n"}{if
($58)print"whitelist_from",$58}' <inputfile

そして次のステップとして、awk は以下のように記述されます。

<condition>{<action>}

でも、あなたは以下のように書いています。

<no condition, so "true" by default>{if (<condition>) <action>}

もっと awk らしく (awk-ish) 書くには以下のようにします。

awk -F"\t"'BEGIN{print"#Autogenerated Whitelist\n"}
$58{print"whitelist_from",$58}' <inputfile

{{comment}}

difficult query to search with in files - nospamatmymaildotcom (2005年09月22日 01時09分06秒)

テキストファイル群を検索しようとしています。他のものがあったら、そのファイルを選択して続きの 8 行を表示することは可能でしょうか。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/ac07dc759baf494e/5957ea88e9073633?hl=ja#5957ea88e9073633


  • やりたいことは以下のようなことですか? - Stein Arne Stors (2005年09月22日 01時09分43秒)
awk '$0==a {
       # Okay, we found "Hi", now use getline x number of times
       # Then check if we have a second match
       getline ;getline
       if ($0==b) {print $0,FILENAME;next} }' a=Hi b=Fine myfile*
  • 大体以下のようなコードになると思います。 - Ted Davis (2005年09月22日 01時11分27秒)
 Array[RN] = $0
 S = RN - 8
 if( $0 ~ pattern2 && S ~ pattern1) exit 1
  • getline を使うと良くないことが多々あります。普通の awk の方法で書き直すことはできますか? - Ed Morton (2005年09月23日 02時47分45秒)
  • 確かに良くないかもしれませんが、これが最小の解法のひとつだと思います。 - Stein Arne Stors (2005年09月23日 02時49分39秒)
  • 以下のようにすることで、巨大なファイルにも対応できます。なぜなら、8 行しかストックしないからです。 - William James (2005年09月23日 02時51分01秒)
/foo/ && a[(NR-8)%8] ~ /bar/ {print "found"}
{ a[NR%8]=$0 }
  • 以下のような方法があります。 - Stein Arne Stors (2005年09月23日 02時52分20秒)
awk '/Hi/{a=1}{if (a) a++} a==4&&/^Fine/ {print FILENAME;next;a=0}' file*

でも、2 番目の要求を見つけた後に、1 番目の要求が必要になってしまいます。

  • このままではうまくいかないと思います。 - Ed Morton (2005年09月23日 02時54分32秒)
  • 最初の "Hi" が見つかった後なので、"next" の後では "a=0" はヒットしません。a がインクリメントされるだけです。
  • "a" を 1 にセットした直後に "a" がインクリメントされます。
  • "{if (a) a++ }" よりも、"a{a++}" といった awk の普通のアプローチが良いでしょう。
  • 以下のようにしてもできるのではないでしょうか? - martin cohen (2005年09月24日 00時13分10秒)
BEGIN{ otherline = 0 }
/anotherstring/{otherline = NR}
/thestring/{if ( (otherline>0) && (NR-otherline == 8) ) {you got it}}
  • 8 行のうちの途中で、anotherstrings や thestring が出現すると変になりませんか? - Ed Morton (2005年09月24日 00時14分52秒)

{{comment}}

Data Validation - shihabvk (2005年09月22日 00時42分07秒)

数値を合計する awk プログラムを作っています。もしも数値以外のものが含まれたら、エラーを表示できますか?

正常な場合

cat file
23
21
-----
will result 44

エラーの場合

cat file
23
21A                                                                                          
-----                                                                                        
Should result .. an error message like   Error in data                                       

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/1091ad10a10823ff/b688cfbb0dd8c28a?hl=ja#b688cfbb0dd8c28a


  • 以下のような感じではいかがでしょうか? - Chris F.A. Johns (2005年09月22日 00時42分42秒)
awk '/[^0-9]/ { print "Error in data"; exit }
     {
       ## your calculation here
     }                                                                                       
END  {
       ## Print results here
     }'                                                                                      
  • +23 とか -23 ではエラーになってしまいます。 - shihabvk (2005年09月22日 00時45分35秒)
  • 以下の方法ではいかがですか? - lorenznl (2005年09月22日 00時46分07秒)
awk '!/[+-]?[0-9]+/ {print "Error in data"; exit}
  • このままでは、数字以外のものを捕らえられません。 - lorenznl (2005年09月22日 00時47分02秒)
awk '!/^[ \t]*[+-]?[0-9]+[ \t]*$/ {print "Error"; exit}'

でいかがでしょうか?

  • 2+3 でエラーにしたいのです。 - shihabvk (2005年09月22日 00時47分57秒)
  • 以下のような方法があります。 - Stein Arne Stors (2005年09月22日 00時50分11秒)
awk '{ if (!/^[+-]?[0-9]+$/) {print $0 " - Error in data in line " NR }
      else print }' file
-1
1
+3
3-4 - Error in data in line 4
3+4 - Error in data in line 5
23+ - Error in data in line 6
asd - Error in data in line 7
  • 以下のような方法があります。 - tink (2005年09月22日 01時03分32秒)
awk '/[^0-9+-]/ { print "Error in data"; exit }
  • awk の組み込み数値変換を使うと、うまくいきそうです。 - Andrew Schorr (2005年09月22日 01時05分32秒)
gawk '$1+0 != $1 {printf "Invalid input: %s\n",$1 > "/dev/stderr"; exit
1} {s += $1} END {print s}'
  • "1.0" とかの場合はどうするんですか? - Ed Morton (2005年09月23日 02時44分31秒)
  • 浮動小数点の場合には簡単に直すことができます。 - Andrew Schorr (2005年09月23日 02時45分25秒)
gawk -v rc=0 '
($1+0 != $1) || ($1 ~ /\./) {
   printf "Invalid input: %s\n",$1 > "/dev/stderr"
   exit rc = 1
}                                                                                            

{s += $1}

END {
   if (!rc)
      print s
}'                                                                                           

{{comment}}

Searching similar patterns in file - chaitanya.sharma (2005年09月22日 00時36分00秒)

月ごとのリストを溜めています。ここで、その月に使われたコラムで繰り返された回数を表示したいのです。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/156c41f81a395b64/d36dba356066e490?hl=ja#d36dba356066e490


  • サンプルがないので、良く分かりませんが、$1 が目的とするものであれば、以下のようにしてできます。 - Ed Morton (2005年09月22日 00時37分05秒)
awk 'd[$1]++ == 1' file
  • UNIX 系であればパイプを使うと簡単です。 - goedel (2005年09月22日 00時37分53秒)
sort -f file | uniq -id

または、ブランクで区切られているのであれば、

cut -d' ' -f1 FILE | sort -f | uniq -id

でもできます。{{comment}}

regex solution to the following problem - Steve Miller (2005年09月18日 20時14分06秒)

"(CP" という文字が含まれているタグまたはエレメントをカウントしたいのです。

<blockquote>
    <para>some sentences here.</para>
    <para>some more sentences here.</para>
    <para>I want to count all words, excluding <para> and <quote> tags,
within the <para> tags of this blockquote if it contains "(CP" as this
paragraph does. (CP </para>
</blockquote>

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/4fe26ae26452b71e/952af99a538c3258?hl=ja#952af99a538c3258


  • <para> は <blockquote> の中にあるものとします。 - Steve Miller (2005年09月18日 20時18分04秒)
  • well-formed XML であれば、<para> はクローズされているとして考えます。 - Jurgen Kahrs (2005年09月18日 20時19分14秒)
 gawk -lxml 'XMLCHARDATA  { if ($0 ~ /\(CP/) print NF, $0 }' /tmp/data

上記はタグを扱うときの最初のステップを示しているだけで、ここから加工することも必要でしょう。

    • Newsgroup でも投稿されていますが、普通の awk で XML を読む方法が紹介されています。
  • 以下のような方法があります。 - William James (2005年09月18日 20時24分28秒)
BEGIN {
  RS = "</?blockquote>"
  FS = "[\n \t]*</?para>[\n \t]*"
}                                                                                            

# If "(CP" is in last <para> ...
NF > 2 && $(NF-1) ~ /\(CP/ {
  count = 0
  for (i=2; i<NF; i++)
  { # Remove <quote> tags.
    gsub( /<[^>]*>/, "", $i )
    count += split( $i, t, /[\n \t]+/ )
  }                                                                                          
  print count
}                                                                                            
  • xmlgawk での解を示しておきます。 - goedel (2005年09月19日 19時14分36秒)
BEGIN {
  XMLMODE=1
  bq_begin=0
  printf("%7s %7s %10s\n", "LINE", "COLUMN", "WORDCOUNT")
}                                                                                            
XMLSTARTELEM == "blockquote" {
  bq_begin=1
  para_begin=0
  bq_start_line = XMLROW
  bq_start_col = XMLCOL
  content = ""
}                                                                                            
XMLENDELEM == "blockquote" {
  if (content ~ /\(CP[ \t\n]*$/) {
    printf("%7d %7d %10d\n", bq_start_line, bq_start_col,
split(content,a))
  }                                                                                          
  bq_begin=0
}                                                                                            
bq_begin && para_begin && XMLCHARDATA {
  content = content " " $0
}                                                                                            
XMLSTARTELEM == "para" {
  para_begin=1
}                                                                                            
XMLENDELEM == "para" {
  para_begin=0
}                                                                                            
END {
  if (XMLERROR) {    printf("'%s' in line %d and column %d with length %d\n", XMLERROR,
XMLROW, XMLCOL, XMLLEN)
    exit(1)
  }                                                                                          
}                                                                                            
  • gawk 3.1.4 を libxml と一緒にビルドしているのに、うまくいきません。-lxml オプションを受け付けません。 - Steve Miller (2005年09月21日 00時53分09秒)
  • 2 つの解があります。 - Jurgen Kahrs (2005年09月21日 00時54分23秒)
  1. デフォルト設定で "make install" します。
  2. configure --enable-static-extensions とします。
  • William James の方法で問題なく動作します。 - Steve Miller (2005年09月21日 00時57分48秒)

{{comment}}


  • XML キタ━━━━━━(゜∀゜)━━━━━━ッ!!!! という感じでしょうか。 - hi_saito (2005年09月18日 20時15分44秒)
  • William James の方法は私も昔使っていたのですが、XML 全てには使えないですね。というか、そんなんで万能なら、xmlgawk いらないですから。 - hi_saito (2005年09月18日 20時26分17秒)
  • ふと Jurgen Kahrs の xmlgawk を見ると、スタティックリンキングではないですか。私もスタティックでビルドしておこう。 - hi_saito (2005年09月18日 20時28分08秒)
  • ユーザーからの xmlgawk ではじめてのプログラムかもしれません。少し泥臭い部分 (XMLSTARTELEM とか XMLENDELEM とか) がありますが、下手に自分でパーサを記述するよりは便利だと思います。 - hi_saito (2005年09月19日 19時18分30秒)

Extract value from neighbouring line within a section - Jonny (2005年09月18日 19時59分57秒)

以下のような file1 があります。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
    ShowIcon    REG_DWORD   0x1
    Name    REG_SZ  Local Area Connection
    PnpInstanceID   REG_SZ  PCI\VEN_10B7&DEV_9200
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
    PnpInstanceID   REG_SZ  SW\{48926476-2CAE-4DED
    Name    REG_SZ  Local Area Connection 2
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
    Name    REG_SZ  Local Area Connection 3
    PnpInstanceID   REG_SZ  SW\{42226676-2CDC-4DFD

Local Area Connection のために PnpInstance?ID の値が欲しいのです。欲しいのは、PCI\VEN_10B7&DEV_9200 という値です。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/949655363d4193c7/ed8dea5d8286894d?hl=ja#ed8dea5d8286894d


  • Windows のレジストリーのようですが、こんなもの使ってるの? - Michael Heiming (2005年09月18日 20時01分12秒)

Linux/FreeBSD/*nix をお勧めします。

awk '/PnpInstanceID/{print $NF}' infile
  • 以下のような結果になりますが、欲しいのは最初だけです。 - Jonny (2005年09月18日 20時02分43秒)
PCI\VEN_10B7&DEV_9200
SW\{48926476-2CAE-4DED
SW\{42226676-2CDC-4DFD
  • 以下のような方法があります。 - Ed Morton (2005年09月18日 20時03分42秒)
gawk -vRS="HKEY_LOCAL_MACHINE" -F"[\n\t]*" '{for (i=2;i<NF;i+=3)                             
info[$i]=$(i+2)}info["Name"]=="Local Area Connection"{print
info["PnpInstanceID"]}' file
  • gawk ならもっと直接的に書けばいいのでは? - Loki Harfagr (2005年09月18日 20時04分57秒)
$ gawk -v RS="    Name    REG_SZ  Local Area Connection\n    "
   '/PnpInstanceID   REG_SZ  /{print $3;exit}'
  • ↑1 つだけマッチする場合や、まったくマッチしない場合にはおかしな挙動になりますよ。 - Ed Morton (2005年09月18日 20時06分52秒)
  • 同一行にあるなら、以下のようにできますよ。 - William James (2005年09月18日 20時07分48秒)
awk "/\tLocal Area Connection\t/ { print $NF }"  file1
  • 残念ながら同一行にはありません。 - Jonny (2005年09月18日 20時08分22秒)
  • 以下のような方法があります。 - William James (2005年09月18日 20時09分18秒)
mawk "/Connection\n/&&gsub(/.*PnpInstanceID\t[^\t]+\t|\n.*/,'')"
RS="HKEY_" file1
  • これは "Local Area Connection" に依存してしまうのでは? - Jonny (2005年09月18日 20時11分37秒)
  • そんなことはありません。 - William James (2005年09月18日 20時11分56秒)

{{comment}}

removing ^M - Thomas Toth (2005年09月18日 19時41分16秒)

gawk での解法はありますか?

cvs-dos では ^M が付きます。ついでに 100x100 のオリジナルデータを 50x50 にします。

以下のように ORS を指定しているのですが、どうして除けないのでしょうか?

BEGIN {FS=";"; ORS=";"}
(NR==2){
   for (loop=1;loop<=NF;loop++){
     if ($loop ~ /RXAO/){
       startf=loop
     }
     if ($loop ~ /DETO/){
       endf=loop+1
     }
   }
}
(NR>2 && $1 ~ /[0-9]/ && $1 !~ /[a-zA-Z]/){
   for (i=startf;i<=endf;i++)
     print($i)
   printf("\n")
}

2 つのことを教えてください。

  1. ORS を使わずに最後のフィールドの ^M を取り除く方法
  2. ^M を取り除くのに ORS を使う方法

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/7c8c2a6b5a206e62/04e7598ec32bf0fc?hl=ja#04e7598ec32bf0fc


  • 以下のような方法があります。 - Ed Morton (2005年09月18日 19時42分17秒)
sub("^M","")
$ cat -v file
11;12;13;14;15^M
21;22;23;24;25^M
31;32;33;34;35^M
41;42;43;44;45^M
51;52;53;54;55^M

これを真ん中の 3x3 にするには、

$ awk -F\; 'NR>=2&&NR<=4{s="";for(i=2;i<=4;i++){printf
"%s%s",s,$i;s=FS}print ""}' file | cat -v                                                    
22;23;24
32;33;34
42;43;44

先頭の 3x3 にするには

$ gawk -F\; 'NR>=1&&NR<=3{s="";for(i=3;i<=5;i++){printf
"%s%s",s,$i;s=FS}print ""}' file | cat -v
13;14;15^M
23;24;25^M
33;34;35^M

^M を除くには、

$ gawk -F\; 'NR>=1&&NR<=3{sub("^M","");s="";for(i=3;i<=5;i++){printf
"%s%s",s,$i;s=FS}print ""}' file | cat -v
13;14;15
23;24;25
33;34;35

ここで、cat -v は control-M を ^M と表示するものです。

  • 以下のような方法があります。 - William James (2005年09月18日 19時48分17秒)
sub( "\r", "" )

以下を試してみてください。

BEGIN {FS=";" ; ORS="" }
{ sub( "\r", "" ) }
(NR==2){
   for (loop=1;loop<=NF;loop++){
     if ($loop ~ /RXAO/)
       startf=loop
     if ($loop ~ /DETO/)
       endf=loop+1
   }                                                                                          
}                                                                                            
(NR>2 && $1 ~ /[0-9]/ && $1 !~ /[a-zA-Z]/){                                                  
   for (i=startf;i<=endf;i++)
     print $i (i<endf ? FS : "")
   print "\n"
}                                                                                            
  • 構文的に仕上げてもらえないでしょうか? - Thomas Toth (2005年09月18日 19時52分10秒)
  • これのことでしょうか? - William James (2005年09月18日 19時52分33秒)
print $i (i<endf ? FS : "")

これは

<評価式> ? <評価式が正しい場合> : <評価式が異なる場合>

であり、以下のように使えます。

 awk "BEGIN{print 1 ? 88 : 77 }"
 88
 awk "BEGIN{print 0 ? 88 : 77 }"
 77
  • RS を用いるのはいかがですか? - Loki Harfagr (2005年09月18日 19時55分02秒)
-v RS='\r\n'
  • でもなんで、awk の解の前に dos-to-unix を使わないんだい? - Roberto Waltman (2005年09月18日 19時56分01秒)

{{comment}}

help me understand this statement. - vihang007 (2005年09月18日 19時22分34秒)

以下のようなものがあります。

awk '!a[$0]++'

重なっている行をテキストファイルから除くのですが、どうしてですか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/845bc4589566f93f/12b02e52a09b3766?hl=ja#12b02e52a09b3766


  • それぞれの行を用いて配列が作られます。(a[$0] の部分) - Loki Harfagr (2005年09月18日 19時23分35秒)

これをインクリメントします。(++ の部分)

a[$0] が 0 の時にプリントします。(! の部分)

  • このようにも書けます。 - William James (2005年09月18日 19時26分50秒)
awk '!($0 in a); {a[$0]}'

{{comment}}

How do I Join a text with many rows in a new text with only one row? - biazoto (2005年09月15日 00時02分53秒)

たくさんの列をひとつの列にするにはどうすればいいでしょう?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/793c3137ca2dc0d4/f0df214990b878cf?hl=ja#f0df214990b878cf


  • 最も簡単な方法は、"tr -d '\n'" です。 - Bill Marcum (2005年09月15日 00時03分59秒)

awk なら

awk '{printf("%s",$0)}'
  • こういうことでしょうか? - Ed Morton (2005年09月15日 00時05分10秒)
$ cat file
line 1
line 2
line 3
$ awk -v ORS= '1' file
line 1line 2line 3$

そうでないなら、簡単な例を出してください。{{comment}}


  • Ed のスクリプトのうまさは、RS と ORS の使い方だと思うのは私だけでしょうか? - hi_saito (2005年09月15日 00時06分47秒)

Let's talk about sex - news.t-online.de (2005年09月13日 22時22分43秒)

いつお互いにセックスしたかを分類したソートされたファイルがあります。

Paul    Louise   2005-04-02 18:00
Fred    Fred     2005-07-07 03:05
Judith  John     2005-06-08 18:00
Fred    Louise   2005-03-02 18:00
Susan   Peter    2005-08-18 17:10
Susan   Tim      2005-09-10 02:00
Joanna   Jaonna  2005-04-09 13:00
Joanna   Jaonna  2005-04-10 13:00
Judith  John     2005-06-09 18:00
....

これを以下のようにグループ化したいのです。

2005-04-09 13:00 2005-04-09 13:00  Joanna Joanna
2005-06-09 18:00 2005-06-08 18:00  Judith John
lastdate firstdate                 Susan Peter Tim
lastdate firstdate                 Paul Louise Fred

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/933fee3986c614d9/74f2e329c68ea1f7?hl=ja#74f2e329c68ea1f7


  • 以下のような方法があります。 - Jurgen Kahrs (2005年09月13日 22時23分15秒)
{
  gsub("-", " ", $3)
  gsub(":", " ", $4)
  t=mktime($3 " " $4 " 00")
  # Remember all persons that occur in the list.
  node[$1] ++
  node[$2] ++
  # Take care of symmetry of the relation.
  p1=$1
  p2=$2
  if (p2<p1) {
    p2=$1
    p1=$2
  }

  # Update the array of first encounters.
  if ((p1, p2) in first) {
    if (t < first[p1, p2])
      first[p1, p2] = t
  } else {
    first[p1, p2] = t
  }

  # Update the array of last encounters.
  if ((p1, p2) in last) {
    if (t > last[p1, p2])
      last[p1, p2] = t  } else {
    last[p1, p2] = t  }
}

END {
  for (i in node) {
    for (j in node) {
      if ((i, j) in first)
        print strftime("%F %H:%M", first[i, j]),
              strftime("%F %H:%M", last[i, j]), i, j
    }
  }
}

結果は以下のとおりです。

2005-04-02 18:00 2005-04-02 18:00 Louise pul
2005-06-08 18:00 2005-06-09 18:00 John Judith
2005-08-18 17:10 2005-08-18 17:10 Peter Susan
2005-04-09 13:00 2005-04-10 13:00 Jaonna Joanna
2005-09-10 02:00 2005-09-10 02:00 Susan Tim
2005-03-02 18:00 2005-03-02 18:00 Fred Louise
2005-07-07 03:05 2005-07-07 03:05 Fred Fred
  • 以下のような方法があります。 - epc8 (2005年09月13日 22時27分28秒)
function min(a,b){
  if(a<b)
    return a
  else
  return b
}

function max(a,b){
  if(a>b)
    return a
  else
    return b
}

{

# create date/time string

  t=$3 " " $4

  x = node[$1]
  y = node[$2]

# if neither listed add a new list

  if (!x && !y) {
    n++
    node[$1]=n
    node[$2]=n
    f[n]=t
    l[n]=t
      }

# add $2 to list of $1

  else if(x && !y) {
    node[$2]=x
    f[x]=min(f[x],t)
    l[x]=max(l[x],t)
  }

# add $1 to list of $2

  else if(!x && y) {
    node[$1]=y
    f[y]=min(f[y],t)
    l[y]=max(l[y],t)
  }

# combine list of $1 and list of $2

  else {
    for(i in node) {
      if(node[i]==y)
        node[i]=x
    }

# combine the min and max date/time too
    f[x]=min(f[x],f[y])
    l[x]=max(l[x],l[y])
    f[x]=min(f[x],t)
    l[x]=max(l[x],t)
  }
}
# collect all the members of each list

END{
  for(i in node) {
    j=node[i]
    group[j]=group[j] " " i
  }
  for(j in group) {
    print l[j],f[j],group[j]
  }
}

結果は以下のとおり。

2005-07-07 03:05 2005-03-02 18:00  Fred Louise Paul
2005-06-09 18:00 2005-06-08 18:00  John Judith
2005-09-10 02:00 2005-08-18 17:10  Peter Susan Tim
2005-04-10 13:00 2005-04-09 13:00  Joanna
  • スパムフィルターにひっかからないようにタイトルを変えませんか? - Jurgen Kahrs (2005年09月13日 22時34分56秒)
  • 以下のように少し変更しました。 - news.t-online.de (2005年09月19日 19時10分06秒)
# combine list of $1 and list of $2

  else {
     # if the x is equal y, we do not have to combine again
     # nothing changed, now your progarm is also fast.
    if(x!=y){

       for(i in node) {
         if(node[i]==y)
            node[i]=x
       }                                                                                    

    }                                                                                       

# combine the min and max date/time too

    f[x]=min(f[x],f[y])
    l[x]=max(l[x],l[y])
    f[x]=min(f[x],t)
    l[x]=max(l[x],t)
  }                                                                                         
  • 短く効果的な awk プログラムを作ってみました。 - goedel (2005年09月21日 00時46分48秒)
!/^[ \t]*$/ {
  if ($1 < $2) {
    couple = $1 " " $2
  } else {                                                                                   
    couple = $2 " " $1
  }                                                                                          

  timestamp = $3 " " $4

  if (couple in firstdate) {
    if (timestamp > lastdate[couple]) {
      lastdate[couple] = timestamp
    } else if (timestamp < firstdate[couple]) {                                              
      firstdate[couple] = timestamp
    }                                                                                        
  } else {                                                                                   
    firstdate[couple] = timestamp
    lastdate[couple] = timestamp
  }                                                                                          
}                                                                                            
END {
  for (couple in firstdate) {
    print lastdate[couple], firstdate[couple], couple
  }                                                                                          
}

結果は以下のとおりです。

2005-08-18 17:10 2005-08-18 17:10 Peter Susan
2005-03-02 18:00 2005-03-02 18:00 Fred Louise
2005-07-07 03:05 2005-07-07 03:05 Fred Fred
2005-04-10 13:00 2005-04-09 13:00 Jaonna Joanna
2005-04-02 18:00 2005-04-02 18:00 Louise Paul
2005-06-09 18:00 2005-06-08 18:00 John Judith
2005-09-10 02:00 2005-09-10 02:00 Susan Tim                                                                                            
  • もっと短く。 - William James (2005年09月21日 00時49分37秒)
NF {
  couple = $1 ":" $2
  if ($1 > $2)
    couple = $2 ":" $1

  timestamp = $3 " " $4

  if (couple in firstdate) {
    if (timestamp > lastdate[couple])
      lastdate[couple] = timestamp
    else if (timestamp < firstdate[couple])
      firstdate[couple] = timestamp
  }                                                                                          
  else {
    firstdate[couple] = timestamp
    lastdate[couple] = timestamp
  }                                                                                          
}                                                                                            

END {
  for (couple in firstdate)
    print lastdate[couple], firstdate[couple], couple
}                                                                                            
  • これだと結果が以下のようになります。 - epc8 (2005年09月22日 00時25分29秒)
Paul    Louise   2005-04-02 18:00
Fred    Fred     2005-07-07 03:05
Judith  John     2005-06-08 18:00
Fred    Louise   2005-03-02 18:00
Susan   Peter    2005-08-18 17:10
Susan   Tim      2005-09-10 02:00
Joanna  Joanna   2005-04-09 13:00
Joanna  Joanna   2005-04-10 13:00
Judith  John     2005-06-09 18:00

でも欲しいのは、

2005-04-09 13:00 2005-04-09 13:00  Joanna Joanna
2005-06-09 18:00 2005-06-08 18:00  Judith John
lastdate firstdate                 Susan Peter Tim
lastdate firstdate                 Paul Louise Fred

のかたちです。そこで少し変更しました。

function min(a,b){
  if(a<b)
    return a
  else
  return b
}                                                                                            

function max(a,b){
  if(a>b)    return a  else
    return b
}                                                                                            

{

# create date/time string
  t=$3 " " $4  x = n[$1]  y = n[$2]
# if neither listed add a new list
  if (!x && !y) {    m++
    n[$1]=m
    n[$2]=m    f[m]=t    l[m]=t  }                                                                                          

# add $2 to list of $1
  else if(x && !y) {    n[$2]=x    f[x]=min(f[x],t)     l[x]=max(l[x],t)  }                                                                                          

# add $1 to list of $2
  else if(!x && y) {    n[$1]=y    f[y]=min(f[y],t)     l[y]=max(l[y],t)  }                                                                                          

# combine list of $1 and list of $2
  else {
# only if $1 and $2 are in different lists
    if(x!=y) {      for(i in n) {        if(n[i]==y)
          n[i]=x      }                                                                                      
    f[x]=min(f[x],f[y])    l[x]=max(l[x],l[y])    }                                                                                        

# combine the min and max date/time too
    f[x]=min(f[x],t)    l[x]=max(l[x],t)  }                                                                                          
}                                                                                            
# collect all the members of each list

END{
  for(i in n) {    j=n[i]    g[j]=g[j] " " i  }                                                                                          
  for(j in g)    print l[j],f[j] g[j]
}                                                                                             

もしくは、

function min(a,b){
  if(a<b)    return a  else
  return b
}                                                                                            

function max(a,b){
  if(a>b)    return a  else
    return b
}                                                                                            

{

# create date/time string
  t=$3 " " $4  x = n[$1]  y = n[$2]
# if neither listed add a new list
  if (!x && !y) {    m++
    n[$1]=m
    n[$2]=m    g[m]=$1    if($1!=$2)      g[m]=g[m] " " $2     f[m]=t    l[m]=t  }                                                                                          

# add $2 to list of $1
  else if(x && !y) {    n[$2]=x    g[x]=g[x] " " $2     f[x]=min(f[x],t)    l[x]=max(l[x],t)  }                                                                                          

# add $1 to list of $2
  else if(!x && y) {    n[$1]=y    g[y]=g[y] " " $1     f[y]=min(f[y],t)    l[y]=max(l[y],t)  }                                                                                          

# combine list of $1 and list of $2
# only if different lists
  else {    if(x != y) {      split(g[y],a)      for(i in a)          n[a[i]]=x      g[x]=g[x] " " g[y]      delete g[y]       f[x]=min(f[x],f[y])      l[x]=max(l[x],l[y])    }                                                                                        
 
# combine the min and max date/time
    f[x]=min(f[x],t)    l[x]=max(l[x],t)  }                                                                                          
}

# display date/time/list

END{
  for(j in g)    print l[j],f[j],g[j]
}
  • 一部もっと短くできます。 - William James (2005年09月22日 00時30分56秒)
> function min(a,b){                                                                         
>   if(a<b)                                                                                  
>     return a                                                                               
>   else                                                                                     
>   return b                                                                                 
> }                                                                                          

function min(a,b){
  if(a<b)
    return a
  return b
}                                                                                            

と書けます。

  • return a < b ? a : b でもいいのでは? - Kenny McCormack? (2005年09月22日 00時32分10秒)
  • return (a+b-abs(a-b)) でもいいのでは? - Ulrich M. Schwar (2005年09月22日 00時32分47秒)

{{comment}}


  • 確かにこれスパムですよね。私もスパムだと思って無視していました。 - hi_saito (2005年09月13日 22時36分47秒)

Need help to reformat complex file - Kevin (2005年09月11日 02時37分07秒)

Some header stuff             xcoord1    ycoord1
  1a   1b   2a   2b   3a   3b   4a   4b    5a   5b
  6a   6b   7a   7b   8a   8b   9a   9b   10a  10b
11a  11b
Some header stuff             xcoord2    ycoord2
  1a   1b   2a   2b   3a   3b   4a   4b    5a   5b
  6a   6b   7a   7b   8a   8b   9a   9b   10a  10b
11a  11b

といったファイルを以下のようにフォーマット変更したいのです。

xcoord1  ycoord1    1a   1b
xcoord1  ycoord1    2a   2b
xcoord1  ycoord1    3a   3b
xcoord1  ycoord1    4a   4b
xcoord1  ycoord1    5a   5b
xcoord1  ycoord1    6a   6b
xcoord1  ycoord1    7a   7b
xcoord1  ycoord1    8a   8b
xcoord1  ycoord1    9a   9b
xcoord1  ycoord1   10a  10b
xcoord1  ycoord1   11a  11b
xcoord2  ycoord2    1a   1b
xcoord2  ycoord2    2a   2b
xcoord2  ycoord2    3a   3b
xcoord2  ycoord2    4a   4b
xcoord2  ycoord2    5a   5b
xcoord2  ycoord2    6a   6b
xcoord2  ycoord2    7a   7b
xcoord2  ycoord2    8a   8b
xcoord2  ycoord2    9a   9b
xcoord2  ycoord2   10a  10b
xcoord1  ycoord1   11a  11b

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/d066c53d949b845d/1e5ebbb185dc4bc2?hl=ja#1e5ebbb185dc4bc2


  • awk ではないけれど、以下のようにしてできます。 - William Park (2005年09月11日 02時38分24秒)
   while read line; do
   set -- $line
   case $line in
     'Some header stuff'*) x=$5 y=$6 ;;
     *) printf "$x $y %s %s\n" "$@" ;;
   esac
   done < file

または、6 つのフィールドである前提があれば、

   csplit file '/^Some header stuff/' '{*}'
   for i in xx*; do
   set -- `< $i`
   x=$5 y=$6
   printf "$x $y %s %s\n" "${@:7}"
   done

awk の解は宿題とします。:-)

  • awk で質問されているのだから、awk で解答してください。しかも、何のスクリプトか書かれていない。 - Ed Morton (2005年09月11日 02時41分28秒)
  • 以下のような方法があります。 - Ed Morton (2005年09月11日 19時46分46秒)
awk -v RS="Some header stuff" '{for(i=3;i<=NF;i+=2)print
$1,$2,$i,$(i+1)}' file
  • ヘッダー部分が固定なので、挙動が変になるのではないでしょうか? - Loki Harfagr (2005年09月11日 19時48分36秒)
  • ヘッダーは可変ですが、必ず 4 つのスペースで区切られ、最初のフィールドが "VELSTK" なので、問題ありません。 - Kevin (2005年09月11日 19時49分58秒)
  • では、以下のような方法ではどうでしょうか? - Loki Harfagr (2005年09月11日 19時50分31秒)
$ awk -v RS="VELSTK [^ ]* [^ ]* [^ ]* [^ ]*" '{for(i=3;i<=NF;i+=2)print $1,$2,$i,$(i+1)}'
  • そうであれば、以下のような方法があります。 - Ed Morton (2005年09月11日 19時52分30秒)
$ awk -v RS="VELSTK" '{for(i=7;i<=NF;i+=2)print $1,$2,$i,$(i+1)}'
  • awk の RS は 1 文字では? - William James (2005年09月11日 19時54分01秒)
  • GNU awk であれば RS が 1 文字という制限はありません。 - Ed Morton (2005年09月11日 19時54分33秒)
$ echo "abcdefghi" | awk -v RS="def" '1'
abc
ghi
  • 以下のような方法があります。 - William James (2005年09月11日 19時55分41秒)
/^VELSTK/ {x=$(NF-1); y=$NF; next}
{ for (i=1; i<NF; i+=2)
    printf "%s %s%5s%5s\n", x,y,$i,$(i+1)
}                                                                                            
  • 間違っていたようなので、修正します。 - Loki Harfagr (2005年09月11日 19時57分16秒)
$ awk -v RS="VELSTK" '{for(i=6;i<=NF;i+=2)print $4,$5,$i,$(i+1)}'
  • Ed の言うことには気をつけろ。彼の頭の中には UNIX 以外の OS はない。 - William James (2005年09月14日 23時58分11秒)
  • sed なら以下のようにできます。 - Loki Harfagr (2005年09月18日 19時19分38秒)
$ sed 's/[[:blank:]\t]/\n/g'

{{comment}}


  • 個人的には Ed の言うことで良いのではないかと思います。UNIX 生まれのコマンドはどうしても shell に依存する部分がありますし、UNIX の awk なら大体 awk -V での結果を出力すれば、話を通じさせることができます。ただし、Windows (DOS) 系だとコンパイル系に依存が多いので、自分の awk と他人の awk が同じ保障があまりないですね。 - hi_saito (2005年09月15日 00時00分46秒)
  • Ed が弁明しており、彼の経歴が分かって面白いのですが、割愛させていただきます。 - hi_saito (2005年09月18日 19時17分51秒)

cgi - Erich Neuwirth (2005年09月11日 02時31分50秒)

awk で cgi を書くときのツールキットがあったように思うのですが、ググっても引っかかりません。

誰か教えてください。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/22a8a192c29118e5/9a618a46eb71e058?hl=ja#9a618a46eb71e058


  • 何をするツールキットですか? - Ted Davis (2005年09月11日 02時32分31秒)
  • 以下を見てください。 - Tim Menzies (2005年09月11日 19時39分46秒)

イントロテキストは以下にあります。

TCP/IP については以下に書かれています。

簡単な例としては以下のようなものがあります。

BEGIN {
 com = "lynx -dump 'cs.wustl.edu/~loui' &> /dev/stdout"
 while (com | getline line) {
   if (flag && line ~ /[0-9]/) { print line }
   if (line ~ /References/) { flag = 1 }
 }                                                                                          
}                                                                                           

また、awk で作られた Wiki は以下にあります。

サーバのログファイルを取得して、それを整形し、midi ファイルに変換するパイプに渡します。ユーザは新しく作られた midi のリンクをクリックすることができます。

{{comment}}

sorting by date across two fields - chazwozzas (2005年09月10日 02時02分30秒)

テキストファイルをソートしようとしています。

31/08/2005 21:34:43
[some plain text here]


01/09/2005 10:26:46
[some other text here]

日付と書かれたインフォメーションでソートを行います。

BEGIN { RS = "" ; FS = "\n" }
{
    arDate[x,NR]=$1
    arDate[x+1,NR]=$2    print arDate[x,NR] " || "arDate[x+1,NR]
}                                                                                            

使っている awk は Windows2000 上の gawk 3.1.3 です。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/75862de18d394966/2fee2c475aaf0c31?hl=ja#2fee2c475aaf0c31


  • ここでは日付の順序は年/月/日で行います。 - William James (2005年09月10日 02時05分06秒)
BEGIN { RS=""; ORS="\n\n" }                                                                  
{
  a[NR] = fix( $0 )
}                                                                                            
END {
  asort( a )
  for (i=1; i in a; i++)
    print a[i]
}                                                                                            

function fix( s   ,date,a,rest )
{ match(s," ")
  date = substr(s,1,RSTART-1)
  rest = substr(s,RSTART)
  split(date,a,"/")
  return a[3]"/"a[2]"/"a[1] rest
}                                                                                            
  • うまくいきました。 - chazwozzas (2005年09月10日 02時06分51秒)
  • 他の方法で示します。 - Loki Harfagr (2005年09月10日 02時08分23秒)
BEGIN{
    RS="";ORS="\n\n"
}                                                                                            
{
    split($1,a,"/");sub(/^[^ ]* /,sprintf("%s/%s/%s ",a[3],a[2],a[1]))
    v[++i]=$0
}                                                                                            
END{
    n=asort(v);
    for(i=1;i<=n;i++){print v[i]}
}                                                                                              

gawk の中でシステムコールしたり、パイプを使ったりしない方が無難だと思いますよ。あと、日付を固定するのに sprintf() を使いましょう。

また、以下のような方法でもできます。

$ echo "01/09/2005 08:06:27"|awk 'BEGIN{ORS=RS="
";FS=OFS="/"};FNR==1{print $3 OFS $2 OFS $1};FNR-1'
2005/09/01 08:06:27

クォート問題はここでは無視します。

  • もう少し簡単にやってみます。 - martin cohen (2005年09月11日 02時14分30秒)
  1. ソートする順序で新しいファイルを出力します。
  2. それをソートします。
  3. データをトリミングします。
awk '{print substr($0,7,4) substr($0,1,2) substr($0,4,2) substr($0,12,8) $0}' infile > tmpfile
sort <tmpfile >outfile
awk '{print substr($0,17)}' outfile >answerfile
  • DOS だと動きません。 - William James (2005年09月11日 02時17分43秒)

{{comment}}

tail -f | gawk on Windows - yong321 (2005年09月10日 01時41分45秒)

GNU utilities for Win32 を Windows XP 上で使っています。でも、tail -f と gawk のコンビネーションがうまく動きません。

C:\>type test.txt
This is a test.
Second line.
C:\>tail -1 test.txt | gawk "{print $1}"
Second

C:\>tail -f test.txt | gawk "{print $1}"
^C^C
C:\>tail -f test.txt | gawk '{print $1}'
gawk: cmd. line:1: '{print
gawk: cmd. line:1: ^ invalid char ''' in expression
^C
C:\>tail -f test.txt 2>&1 | gawk "{print $1}"
^C^C
C:\>tail -f test.txt 1>&2 | gawk "{print $1}"
This is a test.
Second line.^C^C

シングルクォートがうまく動作しません。ただし、Cygwin ではうまく動作します。

$ cd /cygdrive/c
$ tail -f test.txt | gawk "{print $1}"
This is a test.
$ tail -f test.txt | gawk '{print $1}'
This

Cygwin を使わずにどうやればうまく動作させることができるでしょうか?http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/7607d1180b29cc79/5387c5073b7b932c?hl=ja#5387c5073b7b932c


  • このツールは使ったことがないが、alt.msdos.batch.nt で聞いてみてはいかがでしょうか? 8/4 にその投稿がありました。- William Allen (2005年09月10日 01時43分26秒)

もしくは fflush() で解決できませんか?

tail -f test.txt | gawk "{print $1};fflush()"
  • やってみましたが、うまく動きませんでした。 - yong321 (2005年09月10日 01時46分00秒)
C:\>tail -f test.txt | gawk "{print $1};fflush()"                                            
^C^C

} を最後に持ってきてもダメでした。

どうも Windows での tail の実装に問題がありそうです。awk95.exe (One True AWK) や perl デモダメでした。

C:\>tail -f test.txt | perl -nle "split / /; print $_[0]"                                    
Terminating on signal SIGINT(2)
^C
C:\>tail test.txt | perl -nle "split / /; print $_[0]"                                       
This
Second

tail -f の -f を除くとうまく動作しましたので、tail の問題だと思われます。

  • Windows の偽のパイプが原因でしょう。 - Bill Marcum (2005年09月10日 01時49分26秒)

"foo | bar" は "foo>hidden_temp_file; bar<hidden_temp_file" のように処理されます。

  • そのファイルはどこにあるのでしょうか? - yong321 (2005年09月10日 01時52分07秒)

Process Explorer というソフトを使って調べると以下のパイプをオープンしています。

\Device\NamedPipe\Win32Pipes.00001204.0000002c

また、gawk も同じハンドル 0x108 のものをオープンしています。しかも、ファイルではなく、パイプです。

  • %WINDIR%\temp ディレクトリに scs1502.tmp のようなユニークな名前で格納されます。 - hi_saito (2005年09月11日 02時07分12秒)
  • そんなことはありません。WindowsXP などの新しい Windows では一時ファイルに書き出すのは間違いでしょう。 - ggrothendieck (2005年09月11日 02時08分47秒)
gawk {print;fflush()} | gawk {print;fflush()}

というのを試すと分かります。

  • WindowsXP でやってみましたが、異なった結果が出ました。 - Eric Pement (2005年09月11日 02時11分08秒)
  C:\tmp>ver
  Microsoft Windows XP [Version 5.1.2600]
  C:\tmp>cat test1.txt
  one line
  two lines
  three lines
  four lines
  LAST line

  C:\tmp>c:\UnxUtils\tail -f test1.txt | c:\UnxUtils\gawk "{print $1}"
  one
  two
  three
  four
  LAST
  ^C^C
  C:\tmp>c:\UnxUtils\tail --version | head -2
  tail (textutils) 2.1
  Written by Paul Rubin, David MacKenzie, Ian Lance Taylor, and Jim Meyering.

  C:\tmp>c:\UnxUtils\gawk --version | head -2
  GNU Awk 3.1.3
  Copyright (C) 1989, 1991-2003 Free Software Foundation.

最後の行が CR/LF か LF で終わっていないのではないでしょうか?

  • アップデートが出ていますので、アップデートしてみてください。 - Timo Salmi (2005年09月11日 19時38分01秒)
 878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
 UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32

 3365706 Apr 15 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUtils.zip
 UnxUtils.zip GNU utilities for native Win32
  • どうも古いバージョンを使っていたようです。 - yong321 (2005年09月11日 23時03分21秒)

{{comment}}


  • MS-DOS 時代にはいろいろ悩んだものですが、以下のようにしても Windows のパイプが特殊だということが分かると思います。 - pop (2005年09月10日 01時54分47秒)
$ cat foo.txt | gawk '{print $0}' > foo.txt

このような処理の場合、Windows や MS-DOS では上書きされますが、UNIX 系 OS では止まってしまいます。パイプが正常に処理されている (gawk でいう fflush() されている) なら、止まって正解ではないでしょうか?

fflush() をやるべきは gawk 側ではなく、tail 側ですよね。

regex back refernces - Ed Morton (2005年09月09日 00時05分33秒)

comp.unix.shell で、正規表現にマッチした時の awk が後方参照を扱えないステートメントの結果の議論が出ていました。

例えば、もしも 3 つの同じ大文字 (たとえば、3 つの "A" または 3 つの "B" であって、"ABC" ではない) のシーケンスを探す場合、(GNU や他の) sed (または perl のようなもの) では以下のようにします。

sed -n '/\([A-Z]\)\1\{2\}/p'

大文字 ([A-Z]) を見つける場合には、同じ文字 (\1) を 2 つ (\{2\}) 付けます。

$ echo "AAA" | sed -n '/\([A-Z]\)\1\{2\}/p'
AAA
$ echo "AAB" | sed -n '/\([A-Z]\)\1\{2\}/p'
$

GNU awk 3.1.4 でいろいろな方法を試しました。

awk --posix '/([A-Z])\\1{2}/'
awk --posix 'gensub(/(/([A-Z])\1{2}/,"","")'

ひとつ、そしてふたつのバックスラッシュのいろいろなコンビネーションを使って、--re-interval や --posix を使いましたが、動くものが得られませんでした。

sed や perl のように awk でも簡単にする方法はありますか? (マッチするコードそのものを書くのはなしです)http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/bb1a6a766b62b60d/1eb3ba0444b958ae?hl=ja#1eb3ba0444b958ae


  • そのとおりです。 - Patrick TJ McPhe? (2005年09月10日 01時23分50秒)

match() や index() を用いる必要があるでしょう。

  • gawk を使った回答です。 - goedel (2005年09月18日 19時11分31秒)
########################## BEGIN of backtick ############
#!/bin/bash

if (($# < 2)) || ! { echo "$2" | egrep -q '^[[:digit:]]+$'; }
then
  echo "usage: ${0##*/} REGEX NUMBER [FILE]..." >&2
  exit 1
fi

REGEX="$1"
NUMBER="$2"
shift 2

/usr/bin/awk -v regex="$REGEX" -v number="$NUMBER" -f <(tail +15 "$0")
"$@"
exit 0
func match_repeated(t,r,n,   a,i,j,s) {
  for (i=1;i<=length(t);++i) {
    u = substr(t,i);
    match(u,r,a)
    s = ""
    for (j=1; j<=n; ++j) {
      s = s a[0]
    }
    if (substr(u, a[0, "start"], length(s)) == s) {
      return i + a[0,"start"] -1;
    }
  }
  return 0
}

使い方は以下のとおり。

$ echo -e "AAAA\nBBB\nSSSS" | backtick '[A-Z]' 4
AAAA
SSSS

{{comment}}


  • Ed Morton からの挑戦状ですかね。直訳に近い形で翻訳してみました。私も適当にやってみましたが、分かりませんでした。 - hi_saito (2005年09月09日 00時12分33秒)

How to skip first 5 lines and process next 8 lines - karenmiddleol (2005年09月08日 23時51分02秒)

最初の 5 行をスキップして、その次の 8 行を処理したい場合のコードを優しく教えてください。http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/0d407b5ab4b7bba5/93356ae156c0bbe2?hl=ja#93356ae156c0bbe2


  • 以下のような方法があります。 - Bob Harris (2005年09月08日 23時51分35秒)
awk 'NR==6,NR==13 {print}' input.file

やりたいことを {...} の中に書いてください。

  • 以下のような方法があります。 - Chris F.A. Johnson (2005年09月08日 23時52分46秒)
awk 'NR <= 5 { next }
     NR > 13 { exit }
     {
      ## process lines 6 to 13 here
     }'                                                                                      

{{comment}}

[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ]


最終更新時間:2007年07月30日 22時13分35秒