コミュニティ/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

お名前
件名
本文

Print new file with only second column in uppercase - burkina (2005年11月23日 01時03分09秒)

3 つのカラムのあるファイルがあります。2 番目のカラムを大文字にしてスペースをなくして表示しようとしています。

awk -F"|" '{print toupper($2) | "tr -d [:blank:]"}' test.dat

でも、どうやれば、最初のカラムを前にして、3 番目のカラムを後にすることができるのでしょうか。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/f1806024da737a54/4419dd554e4cdd8a?hl=ja#4419dd554e4cdd8a


  • tr は必要ありません。 - Ed Morton (2005年11月23日 01時03分28秒)
awk -F"|" '{gsub(/[[:blank:]]/,"",$2);print toupper($2)}' test.dat

また、以下のようにすればいいのです。

awk 'BEGIN{FS=OFS="|"}{gsub(/[[:blank:]]/,"",$2);$2=toupper($2)}1' test.dat

つまり、

awk '
BEGIN{FS=OFS="|"}       # Set the input field separator and
               # output field separator both to the
               # same character, "|".
{
gsub(/[[:blank:]]/,"",$2)   # Replace all blank characters in "$2"
               # with nothing, i.e. delete all blank
               # characters from $2.
$2=toupper($2)          # Convert $2 to all upper case
}
1               # Specify a true condition (i.e. "1")                       # and so invoke the default action
               # (i.e. print $0)
' test.dat

ということです。

が参考になるでしょう。

{{comment}}

finding field containing string - vrkid0 (2005年11月23日 00時53分55秒)

ある文字列を含むフィールドを見つけ、そのフィールドだけを表示するにはどうすればいいでしょうか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/0c5c8472744393ae/7ffe313ff0b76e28?hl=ja#7ffe313ff0b76e28


  • awk の文献を読めば載っていますよ。 - ars Kellogg-Stedman (2005年11月23日 00時54分25秒)
awk '$5 ~ /string/ {print $5}'

これは、5 番目のフィールドが string を含めば 5 番目のフィールドを表示します。

  • 既に James が投稿していて解決しました。 - vrkid0 (2005年11月23日 00時57分28秒)
  • どうやって「ある文字列」、「あるフィールド」を見つけられるんだ。 - James (2005年11月23日 00時58分43秒)
$ echo string bbb ccc string ddd | awk '{for (i=1;i<=NF;i++) {if ($i ~
/string/) {print i,$i}}}'
1 string
4 string

{{comment}}

newbie & windows - barkie (2005年11月23日 00時47分04秒)

GNU のものではなく、Windows に特化した gawk のドキュメントはありますか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/5d1d1f7a8fe4ba71/d2edce5c8b763bab?hl=ja#d2edce5c8b763bab


  • 以下のようなものがあります。 - William James (2005年11月23日 00時48分14秒)
gawk "BEGIN{print \"Hello, world!\"}"

また、複数行のプログラムには、

gawk -f myprog.awk

です。

  • 以下のようなことがあります。 - nt4-ever (2005年11月23日 00時49分24秒)

コマンドラインでは、% は %% となり、コマンドラインでは \% で実行できます。

<, >, |, & 

はダブルクォートで囲い、他のものは ^ をつけます。

  • echo ^< で <が出るんですねえ >cmd.exe。知らんかった。 - きむら (2005年11月23日 16時13分46秒)
  • ちゃんとしたドキュメントではないですが、以下のようなものがあります。 - Eric Pement (2005年11月24日 23時27分59秒)
  • 私は GNU for Win32 を使っているのですが、うまくいきません。誰かオススメの他のものを知っていますか? - barkie (2005年11月29日 22時14分23秒)
  • 8 進数表記を使うことができます。 - John Savage (2005年11月30日 23時38分57秒)
gsub("\047","",$5)

もしもダブルクォートをエスケープするのであれば、

gsub(\"\047\",\"\",$5)

といった感じでしょうか。

  • 以下の Windows のものは完全にシングルクォート対応です。 - Eric Pement (2005年12月10日 20時25分43秒)

{{comment}}


  • なかなか面白そうなドキュメントなので、時間があれば翻訳してもいいかなと思っています。 - hi_saito (2005年11月24日 23時28分51秒)

Read strings from one file and search for them in a directory containing htm files - Meghavvarnam (2005年11月21日 23時15分57秒)

一語ごとのファイルがあります。

これを別のディレクトリにある 100 の HTML ファイルの中から検索して、見つかったら他のファイルに書き出します。また、見つからない場合は無視します。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/6c4928ec83516367/4e59a1cbffca954b?hl=ja#4e59a1cbffca954b


  • shell のループで grep を使えばいいのではないでしょうか。 - Juergen Kahrs (2005年11月21日 23時16分52秒)
  • 以下のようなものを試しました。 - Meghavvarnam (2005年11月21日 23時17分13秒)
do
   echo "SEARCHING" $(string) ". . . ."
   grep string ./htm/*.htm
done

でも、動作しませんでした。

  • comp.lang.awk ではなく、comp.unix.shell で質問してはどうでしょうか。 - Ed Morton (2005年11月21日 23時18分49秒)
while IFS= read -r string
do
    echo "SEARCHING $(string) . . . ."
    grep "$string" htm/*.htm
done < allStrings.txt

これを試してみてください。

また、以下のサイトが参考になるでしょう。

  • 以下のものはどうでしょうか? - Chih-Cherng Chin (2005年11月21日 23時20分51秒)
while read string
do
   grep "$string" ./htm/*.htm >/dev/null 2>&1
   if [ $? -eq 0 ]; then echo "$string"; fi
done < ./allStrings.txt

また、grep が $string にマッチした時に 0 を返すので、以下の方法も試してみてください。

while read string
do
   grep "$string" ./htm/*.htm >/dev/null 2>&1 && echo "$string"
done < ./allStrings.txt
  • 一語が一行なら以下のものを試してみてください。 - Bob Harris (2005年11月21日 23時24分46秒)
awk '
    FNR == 1 { filecount++ }
    filecount == 1 { match_line[$0]=1 }
    filecount != 1 { if ( $0 in match_line ) print $0 }
' ONE.STRING *.htm >output.file

一語が HTML にあるものであれば、以下を試してみてください。

awk '
    FNR == 1 { filecount++ }
    filecount == 1 { match_string[$0]=1 }
    filecount != 1 {
        for( str in match_string ) {
            if ( $0 ~ str ) print $0
        }
    }
' ONE.STRING *.htm >output.file

2 つめのものは CPU パワーを食います。

{{comment}}

awk behavior with tab separated file - David Kritzberg (2005年11月19日 21時17分01秒)

以下のものを使っています。

  • GNU sed version 4.1.4
  • GNU Awk 3.1.4
  • GNU bash, version 3.00.16(1)-release (i386-redhat-linux-gnu)
  • Linux 2.6.13-1.1532_FC4 #1 i686 athlon i386 GNU/Linux

タブ区切りのファイルを処理していましたが、イタリアか UK からグラフィックコードの部分を使ったものを送付してきました。

どうすればいいのでしょうか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/6e75a5ca3685c0e7/3d126b5589b003d7?hl=ja#3d126b5589b003d7


  • 以下のように FS を定義すればうまくいくのではないでしょうか? - Janis Papanagnou (2005年11月19日 21時17分59秒)
BEGIN {FS="\t"}

{{comment}}

Negate of a group - vinod (2005年11月19日 20時57分06秒)

C++ で // からはじまる部分を無視しようとしています。

でも、コメントは

<space><space>... //

のように始まる場合もあります。

例えば、(\s*\/\/) のような正規表現でマッチさせようと思っているのですが、どうすればいいのでしょうか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/a90bd974bc971103/c97a7f155d2f51f8?hl=ja#c97a7f155d2f51f8


  • 以下を試してみてください。 - William James (2005年11月19日 20時57分36秒)
/^[ \t]*\/\// { next }
  • 必ずスペースかタブで始まっているのであれば、以下のようにできます。 - Ed Morton (2005年11月19日 20時58分48秒)
/^[[:space:]]*\/\// { next }

もしも、コメントをストリップするだけでいいのであれば、gcc -E などを使ってみてはいかがでしょうか?興味があれば、comp.unix.shell に投稿してみてください。

  • 該当する部分を除外するのではなく、該当しない正規表現が欲しいのです。 - vinod (2005年11月19日 21時01分20秒)
  • まず、私や、William が投稿したもので良いのかどうかを知らせてください。 - Ed Morton (2005年11月19日 21時02分06秒)
  • 以下のようなサンプルがあるとします。 - vinod (2005年11月19日 21時03分24秒)
1)// Search <something>
2)if(<something>)
3){
4)    do <something>;
5)}

6)     //Comment <something>
7)int <something>;

ここで、ある正規表現を指定すると、1, 6 行目が出ずに、2, 4, 7 行目が出てきて、欲しいのです。

  • 良く分からないのですが、質問させてください。 - Ed Morton (2005年11月19日 21時05分42秒)
  1. 3, 5 行目は? 5, 6 行目の間のスペースは?
  2. まだ回答をもらっていませんが、以下を試してみてください。
awk '/^[[:space:]]*\/\//{next}1' file
  • 以下を試してみてください。 - Janis Papanagnou (2005年11月19日 21時08分25秒)
/^[[:space:]]*\/\// { next } 1
  • もう少し、どういうことをやりたいのかを FSA (Finite State Automaton = 正規文法に対応する構文解析オートマトン) 的に書かないと分かりません。 - Ulrich M. Schwarz (2005年11月19日 21時12分52秒)

この FSA をどうやって正規表現にするか、できるかを議論する必要があります。

{{comment}}

Perl - Bitochon (2005年11月19日 20時50分15秒)

Perl でそれぞれの行に追加する方法が分かりますか?

フィールド1 フィールド2 フィールド3

とスペースで区切られていて、これに「フィールド4」を追加したいのです。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/f03baf63614f11b3/8213fdafb11682e3?hl=ja#8213fdafb11682e3


  • こんなのでどうでしょうか? - Minh (2005年11月19日 20時50分50秒)
sed '/^./s/$/ Field4/ perl-file

または

awk '$0 !~ /^$/ {print $0,"Field"}' perl-file
  • Active Perl を使っていますが、そんなコマンドはありません。 - Bitochon (2005年11月19日 20時51分53秒)
  • sed も awk も Perl コマンドではありません。本物の OS をインストールすれば使えるようになりますよ。 - Michael Heiming (2005年11月19日 20時53分17秒)

{{comment}}


  • 投稿者もひどいけど、「本物の OS」って何よ? (w - hi_saito (2005年11月19日 20時53分45秒)

new to awk - fueztel (2005年11月19日 20時44分47秒)

サンプルのような入力ファイルを変換したいのです。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/a53a5e142a546b6f/27cc8e47c31c4427?hl=ja#27cc8e47c31c4427


  • それだけじゃ、何をどうすればいいのか分かりません。 - Kenny McCormack? (2005年11月19日 20時45分16秒)
  • IE から投稿されているっぽいので、他のツールで投稿してみてください。 - Ted Davis (2005年11月19日 20時46分13秒)

{{comment}}

general compression with awk - Rufus T. Firefly (2005年11月17日 22時50分10秒)

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

a
a
a
a
b
a
b
a
b
c
d
d

これを以下のようにします。

4 a
2 b a   <-- note pattern [b a] spans several lines
1 b
1 c
2 d

または、

3 a
3 a b   <-- or [a b] here
1 c
2 d

でも構いません。

これは、uniq と似ています。

$ cat example |uniq -c |sort |uniq -c
     2       1 a
     3       1 b
     1       1 c
     1       2 d
     1       4 a

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/01d46730a0dc4183/c14281c940db1936?hl=ja#c14281c940db1936


  • 例えば、2 倍の長さだとします。 - Ed Morton (2005年11月17日 22時50分50秒)
a
a
a
a
b
a
b
a
b
c
d
d
a
a
a
a
b
a
b
a
b
c
d
d

これは

2 a a a a b a b a b c d d

となるべきですか?

3 a
3 a b
1 c
2 d
3 a
3 a b
1 c
2 d

となるべきですか?それとも?

以下のようにしたいとすれば、awk でどうやるかをお手伝いすることはできそうです。

2 3 a 3 a b 1 c 2 d
  • まず、以下のところを見てください。 - Ed Morton (2005年11月17日 22時54分35秒)
  • こういったものは "run length encoding" と呼ばれます。Kernighan と Pike の書いた「The Practice of Programming」などを読まれた方が良いでしょう。 - Michael Zawrotny (2005年11月19日 10時58分29秒)
  • awk ではありませんが、簡単な ruby の方で示します。 - William James (2005年11月19日 11時04分27秒)
def compress( data )

  if "" == data
    return [ ]
  end

  params = [ 0, 1, data, "", "" ]

  data.scan( /[^\n]+\n/ ) { |s|
    before = $~.pre_match
    s << $~.post_match
    s =~ /\A(.+\n)\1+/m
    if $&
      saved_bytes = $&.size - $1.size
      times = $&.size / $1.size
      if saved_bytes > params.first
        params = [ saved_bytes, times, $1, before, $~.post_match ]
      end
    end
  }

  [ compress(params[-2]), params[1], params[2], compress(params[-1]) ]
end

data = ARGF.read

compress( data ).flatten.compact.each_with_index { |x,i|
  if i%2 == 0
    print x, " "
  else
    puts x.gsub(/\n/, " ").strip
  end
}
  • 実際には以下のようなサンプルになりました。 - Rufus T. Firefly (2005年11月20日 19時25分46秒)
2 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a b c
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a b c a a a a a a a a a a a a a a a a a
a a a
2 a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
a a a a a a a a a a a a a a a a a
1 a b c
2 a a a a a a a a a a a a
1 a

これを以下のように圧縮します。

1 a C7 00 01 01 C6 C8
2 b C6 00 01 02 C5 C8
3 c C7 00 02 01 C5 C8

これを awk でやりたいのですが、以下のようなアイデアを考えています。

BEGIN   { m=rep=0 }
        { r=p=NR-nr0                            # position p=1,2,..
          while(r--) if(n=N[q=p-r,$0]++) break  # q=1,2,..,p
          if(n && !rep) rep=q                   # position q repeated!
          if(rep) m=p-rep                       # m after repeat
          print p, q, rep, m, n=N[q,$0], $0
        }
  • 以下のところを参照してみてください。 - nt4-ever (2005年11月20日 19時29分39秒)
  • 新しくしてみました。 - William James (2005年11月20日 19時31分44秒)

オリジナルだと、

3 a
3 a b
1 c
2 d

と出力されて、新しいサンプルだと以下のように表示されます。

176 a
4 1 a b c 196 a
1 a b c
25 a
def compress( data )

  if "" == data
    return nil
  end

  params = [ 0, 1, data.dup, "", "" ]

  data.scan( /[^\n]+\n/ ) { |s|
    before = $~.pre_match
    s << $~.post_match

    s =~ /\A(.+?\n)\1+/m

    if $&
      saved_bytes = $&.size - $1.size
      times = $&.size / $1.size
      if saved_bytes > params.first
        params = [ saved_bytes, times, $1, before, $~.post_match ]
      end
    end

  }

  if params.first == 0
    [ compress(params[-2]), params[1], params[2],
      compress(params[-1]) ]
  else
    [ compress(params[-2]), [params[1], compress(params[2])],
       compress(params[-1]) ]
  end
end

def num?(x); x.class.to_s=="Fixnum"; end

def show_line( ary )
  ary = ary.flatten.compact
  limit = ary.select{|x| num?(x) }.size > 2 ? 1 : 0
  ary = ary.inject([]){|a,x|
    a << x unless num?(x) && num?(a.last) && a.size > limit
    a
  }
  puts ary.map{|x| x.to_s.gsub("\n"," ").strip}.join(" ")
end

def show( ary )
  ary.compact!
  if ary == ary.flatten
    show_line( ary )
  else
    ary.each {|x|
      x.compact!
      if num?(x.first)
        show_line( x )
      else
        show( x )
      end
    }
  end
end

data = ARGF.read
show( compress( data ) )
  • 最初のオリジナルのものは以下のようになります。 - Loki Harfagr (2005年11月29日 22時11分50秒)
a 4
b 1
a 1
b 1
a 1
b 1
c 1
d 2

以下のようなものでできます。

$ cat RLEinawk.awk
BEGIN{
###     print "========="
}
(imp[$0]>0){
        pot=$0
        imp[pot]++;
###     print "["FNR"] put "$0" in accu, count "imp[$0]
        next
}
{
###     print "["FNR"] We read a newt "$0", first depot "pot" ->"imp[pot]
        if(FNR>1)print pot" "imp[pot]
        imp[pot]=0
        pot=$0
###     print "Then put the newt "pot" into accu"
        imp[pot]++
        next
}
END{
###     print "In the end, depot the rest"
        if(FNR>1)print pot" "imp[pot]
###     print "========="
}
  • 多分、uniq -c のものを使っていますね。 - Rufus T. Firefly (2005年11月30日 23時36分56秒)
$ uniq -c example
     4 a
     1 b
     1 a
     1 b
     1 a
     1 b
     1 c
     2 d

なのですが、要点が良く分かりません。

  • Perl だったら以下のようにできます。 - James (2005年12月07日 01時03分49秒)
#!/bin/env perl -w

my ($match, $prev, $next, $a, $b, $m, $c);
$_ = join "",<>;

while (/(.+?)\1{1,}/gs) {
        $match = $&;
        $prev = $`;
        $next = $';
        if ($prev) {for $b (split /[\s\n]/,$prev) {print "1 $b\n" if
$b}};
        $a = $1;
        $m = $match;
        $c = 0;
        $c++ while $m =~ /$a/g;
        $a =~ s/\n/ /g;
        $a =~ s/(^\s+|\s+$)//;
        print "$c $a\n" if $a;
        s/$prev$match//;
}
print $next;

{{comment}}


  • いろいろ見てみると面白い情報がたくさん…。やはり、プリンストン大学ですか。すげー。 - hi_saito (2005年11月17日 22時57分48秒)

add a number once per change - ayman_zekry (2005年11月16日 00時28分40秒)

     test1   6556
     test1    666776
     new      66566
     new   jjhhhhg

のようなファイルがあり、最初のフィールドが切り替わるときに数字を挿入しようとしています。

-999    test1     6556
         test1     666776
-999     new      66566
         new      jjhhhhg

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/671a06211cc03f00/b3184688414141b9?hl=ja#b3184688414141b9


  • 以下のようにすればいいです。 - Steffen Schuler (2005年11月16日 00時29分03秒)
#!/usr/bin/awk -f
{ if ($1 == f) {
     print "    ", $0
   } else {
     print "-999", $0
     f = $1
} }
  • 既に習っているはずですよ。 - Ed Morton (2005年11月16日 00時29分52秒)
awk '$1!=p{n++}{print n,$0;p=$1}' file

これを変更すると、

awk '$1!=p{n="-999"}{print n,$0;p=$1;n=""}' file

もしくはスペースの並びを保持したいなら、

awk '$1!=p{n="-999"}{print n,$0;p=$1;gsub(/./," ",n)}' file

のようにします。

{{comment}}

more generation of sequences - Sebastian Luque (2005年11月16日 00時26分35秒)

以下のような時間のセットを用意します。

25/08/2005,11:00:10,field3,field4
25/08/2005,11:01:10,field3
25/08/2005,11:02:10,field3,field4,field5
25/08/2005,11:05:10,field3,field4
25/08/2005,11:06:10,field3

25/08/2005,11:09:10,field3,field4,field5,field6
,

これを以下のように時間のならびに変更しようとしています。

25/08/2005,11:00:10,field3
25/08/2005,11:01:10,field3
25/08/2005,11:02:10,field3
25/08/2005,11:03:10,
25/08/2005,11:04:10,
25/08/2005,11:05:10,field3
25/08/2005,11:06:10,field3
25/08/2005,11:07:10,
25/08/2005,11:08:10,
25/08/2005,11:09:10,field3
25/08/2005,11:10:10,

これを William のスクリプトで処理します。

BEGIN {
  FS = OFS = ","
  increment = 60
}

{
  oldbeg = beg
  if (NF != 3 || $1 == "") next
  beg = beg_time($1, $2)
  if (beg > oldbeg + increment) {
    for (i = oldbeg + increment; i < beg; i += increment)
      print format_time(i) ","
  } else {
    print
  }
}

# Input: 26/04/2005 08:30:00
# Output: 2005 04 26 08 30 30
function fix_date_string(s) {
  split(s, a, /[ :\/]/)
  return sprintf("%s %s %s %s %s %s",
         a[3], a[2], a[1], a[5], a[6], a[7])
}

function beg_time(d, t) {
  timestr = d " " t
  return mktime(fix_date_string(timestr))
}

function format_time(timestamp) {
  return strftime("%d/%m/%Y,%H:%M:%S", timestamp);
}

でも時間のならびになりませんでした。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/d980ac785925c48a/0d1c80a47aebfc36?hl=ja#0d1c80a47aebfc36


  • 以下のものを試してみてください。 - Steffen Schuler (2005年11月17日 22時43分31秒)
#!/usr/bin/gawk -f
BEGIN {
   FS = OFS = ","
   increment = 60
}

{
   oldbeg = beg
   if (NF < 3 || $1 == "") next
   beg = beg_time($1, $2)
   if (oldbeg != 0 && beg > oldbeg + increment) {
     for (i = oldbeg + increment; i < beg; i += increment)
       print format_time(i) ","
   }
   print $1, $2, $3
}

# Input: 26/04/2005 08:30:00
# Output: 2005 04 26 08 30 30
function fix_date_string(s,     a) {
   split(s, a, /[ :\/]/)
   return sprintf("%s %s %s %s %s %s",
         a[3], a[2], a[1], a[4], a[5], a[6])
}

function beg_time(d, t) {
   timestr = d " " t
   return mktime(fix_date_string(timestr))
}

function format_time(timestamp) {
   return strftime("%d/%m/%Y,%H:%M:%S", timestamp);
}

{{comment}}

add increment field when first field changes - ayman_zekry (2005年11月16日 00時19分33秒)

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

Name1       aaa        bbbb
Name1       ffd         hhghg
Name1       dffg       ghhhh
Name2       rtrt        dfff
Name2       rrtfr       gtt
Name2       dsddf      gfggf
Name2       ffffg       gfgf
NAme3       fdffg      hhgh

これを以下のように最初のフィールドが異なった場合にインクリメントすることは可能ですか?

1    Name1    aaa     bbbb
1    Name1    ffd       hhghg
1    Name1    dffg     ghhhh
2    Name2    rtrt      dfff
2    Name2    rrtfr     tgtt
2    Name2    dsddf   gfggf
2    Name2    ffffg     gfgf

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/ebf7ca04c2d6774f/853156267202e476?hl=ja#853156267202e476


  • 以下のもので動作しますか? - Sebastian Luque (2005年11月16日 00時20分00秒)
{
  nid = substr($1, match($1, /[0-9]+$/), length($1))
  print nid, $0
}
  • 以下のようにしてできます。 - Ed Morton (2005年11月16日 00時20分40秒)
awk '$1!=p{n++}{print n,$0;p=$1}' file
  • 以下のようにしてできます。 - Kenny McCormack? (2005年11月16日 00時22分00秒)
awk '$1!=p{n++;p=$1}{print n,$0}' file
  • 以下のようにしてできます。 - Steffen Schuler (2005年11月17日 22時42分36秒)
#!/usr/bin/awk -f
BEGIN {OFS = "\t"}
$1 != f {++i; f = $1}
{print i, $0}

{{comment}}

static linked awk/gawk binary for windows - Matthias Teege (2005年11月14日 22時44分08秒)

Windows 用のスタティックリンクの awk/gawk のバイナリはありますか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/e86b91ac72e0f2de/70493804bc0758e0?hl=ja#70493804bc0758e0


  • 以下のところがあります。 - William James (2005年11月14日 22時44分37秒)
普通の awk (awk95.exe)
http://cm.bell-labs.com/cm/cs/awkbook/index.html

Kernighan 自信のページ (awk の "k" の人です)

Gawk
http://unxutils.sourceforge.net/

UnxUpdates?.zip を落としてください。

{{comment}}

AWK, condition other then AND ?? - Krzysiek (2005年11月13日 20時49分31秒)

/usr/local/bin/awk -F":" --assign=grp=$GET_grupa --assign=login=$GET_login -
-assign=name=$GET_imie --assign=uid=$GET_uid --assign=gid=$GET_gid --assign=
surname=$GET_nazwisko 'split($5,ar,"[ ,]") && ($1==login && $4==grp &&
toupper(ar[1])==toupper(name) && toupper(ar[2])==toupper(surname) ) {print
$0"<br>"}' /etc/passwd

これは awk で && と書いているように AND の場合を表示するスクリプトです。しかし、$GET_login が空の場合、$GET_grupa が 5000 (awk grp が 5000) にセットするのですが、この際に何も返しません。/etc/passwd の $1 が空でない場合に何も返しません。

フィールドが空でも $4 にマッチするものは返したいのですが、どうすればいいのでしょうか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/bf7a6b7e8843e287/a56852100f1d1baa?hl=ja#a56852100f1d1baa


  • 以下のようにします。 - William James (2005年11月13日 20時49分55秒)
BEGIN {
  FS = ":"
  grp = ENVIRON[ "GET_grupa" ]
  login = ENVIRON[ "GET_login" ]
  name = ENVIRON[ "GET_imie" ]
  surname = ENVIRON[ "GET_nazwisko" ]
}

split($5,ar,"[ ,]") && (""==login || $1==login) && $4==grp &&
toupper(ar[1])==toupper(name) && toupper(ar[2])==toupper(surname){
  print $0 "<BR>"
}
  • shell から awk の変数スタイルにした方が良いでしょう。 - Ed Morton (2005年11月13日 20時52分06秒)
  • 別に驚くことではありません。split() の仕様です。 - news.t-online.de (2005年11月13日 20時53分21秒)
echo "hello" | awk '{print split("",a)}'
0

なので、

'(split($5,ar,"[ ,]") + 1) && ($1==login && $4==grp &&
toupper(ar[1])==toupper(name) && toupper(ar[2])==toupper(surname) )
{print $0"<br>"}' /etc/passwd

とすれば常に表示します。

{{comment}}

printing (output) - Sebastian Luque (2005年11月13日 02時08分03秒)

{print FILENAME, $0}

は問題なく期待通りの結果を出しますが、

{print $0, FILENAME}

は無視されています。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/230c839d12984ccf/bb45cde1fdfcbecf?hl=ja#bb45cde1fdfcbecf


  • OS は何ですか? - pop (2005年11月13日 02時08分29秒)
  • Debian GNU/Linux です。また、これは DOS ファイルのときのみ発生します。 - Sebastian Luque (2005年11月13日 20時42分12秒)
  • 以下の部分を加えてください。 - William James (2005年11月13日 20時42分33秒)
{sub(/\r/,""; print $0, FILENAME}

{{comment}}

converting a paragraphs into comma delimited text tables - ari.rennt (2005年11月12日 21時01分53秒)

以下のようなテキストファイルを変更したいと考えています。

title1: paragraph1.
(space)
title2: paraphraph2

例えば、

ALLERGIES: He has no known drug allergies.

IMMUNIZATIONS: up to date.

BIRTH HISTORY: He was born via cesarean section secondary to repeat.
This is usually a paragraph of data with multiple lines. Sometimes the
paragraph text contains colons and numbers as well.

これを以下のように変更します。

"ALLERGIES" "IMMUNIZATIONS" "BIRTH HISTORY"
"He has no known drug allergies. " "up to date." "He was born via cesarean section secondary to repeat."

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/9a4b207df56508e2/601ffba2642d8f4b?hl=ja#601ffba2642d8f4b


  • どこにスペースがあればいいのかを明確にしてくれると助かります。 - Ed Morton (2005年11月13日 02時03分51秒)
$ awk -vRS="" -F: '{t[NR]=$1;$1="";r[NR]=$0}END{for(i=1;i<=NR;i++)printf
"\"%s\" ",t[i];print "";for(i=1;i<=NR;i++)printf "\"%s\" ",r[i];print
""}' file
"ALLERGIES" "IMMUNIZATIONS" "BIRTH HISTORY"
"  He has no known drug allergies." "  up to date." "  He was born via
cesarean section secondary to repeat."
  • convert.awk として保存して、以下のように実行してください。 - William James (2005年11月13日 20時39分37秒)
gawk --re-interval -f convert.awk myfile.txt  >outfile.txt
BEGIN {
  Width = 70
  if ( "j" !~ /j{1}/ )
  { print "Must run with 'gawk --re-interval'."
    exit
  }
  # A blank line may contain blanks.
  RS = "\n([ \t]*\n)+"
}

match($0, /: */) {
  header = header " \"" substr($0,1,RSTART-1) "\""
  text = text " \"" strip( substr($0,RSTART+RLENGTH)) "\""
}

END {
  display(  header )
  display(  text )
}

function display( s )
{ s = strip( s )
  gsub( /[ \t\n]+/, " ", s )
  while ( length(s) > Width && match( s, /^.{1,70}[ \t]+/ ) )
  { print strip( substr( s, 1, RLENGTH ) )
    s = substr( s, RLENGTH + 1 )
  }
  if ( s )    print s
}

function strip( s )
{ gsub( /^[ \t]+|[ \t]+$/, "", s )
  return s
}

{{comment}}

Misunderstanding of short script behaviour - Clemence Magnien (2005年11月12日 20時56分37秒)

小さなスクリプトですが、その動作がわからなくなりました。

{
if($1 == "a")
#  print $0;
  word = $1;
  print "word : ", word;
}

これは全ての行に対して、最初のフィールドが a であれば、"word : a" と表示するものだと思っていました。ところが、

$ cat test2
a 1
b fd

という入力ファイルに対して、

word :  a
word :  a

と 2 行出てしまいます。

しかも、print $0 のコメントを外すと、

a 1
word :  a
word :  b

となります。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/412f126de01a6b0c/bfc7bdc3b25a8290?hl=ja#bfc7bdc3b25a8290


  • if 文で括弧を付け忘れていました。 - Clemence Magnien (2005年11月12日 20時57分18秒)
  • awk では if を使わないのが普通でしょう。 - Ed Morton (2005年11月12日 20時58分21秒)
$1 == "a" {
#  print $0;
   word = $1;
   print "word : ", word;
}

{{comment}}

Extract filename from path - Jeroen Gouma (2005年11月12日 20時48分04秒)

FILENAME からファイル名だけを抜き出すことはできますか?

FILENAME = c:\test\input\data.txt

ここから、data.txt だけが欲しいのです。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/9245fd795d1fe150/78b6dca481a4185d?hl=ja#78b6dca481a4185d


  • どちらかでできます。 - Ed Morton (2005年11月12日 20時48分30秒)
c = split(FILENAME,arr,"\\"}
f = arr[c]
print f

または

f = FILENAME
sub(/.*[\\]/,"",f)
print f
  • 以下のようにしてできます。 - William James (2005年11月12日 20時49分28秒)
fname=FILENAME; sub(/.*\\/, "",fname)
  • 以下のようにしてできます。 - pop (2005年11月12日 20時50分38秒)
fnam=ary(split(FILENAME,ary,"\\"));
print fnam;
  • 以下のようにしてできます。 - martin cohen (2005年11月12日 20時51分23秒)
k = match(str, /\\[^\]+$/) # with appropriate quoting for \\
last = (k == 0 ? str : substr(str, k+1))

{{comment}}

Help with arrays - surferelf (2005年11月12日 20時44分57秒)

Web ログの集計を考えています。

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

2005-01-01 blah blah blah blah blah blah 192.168.1.1 blah blah blah
2005-01-01 blah blah blah blah blah blah 192.168.1.3 blah blah blah
2005-01-02 blah blah blah blah blah blah 192.168.1.2 blah blah blah
2005-02-01 blah blah blah blah blah blah 192.168.1.5 blah blah blah
2005-02-02 blah blah blah blah blah blah 192.168.1.5 blah blah blah
2005-02-02 blah blah blah blah blah blah 192.168.1.1 blah blah blah

これを以下のように集計したいのです。

2005-01 total number of hits: 3
2005-01 unique hosts served: 3

2005-02 total number of hits: 3
2005-02 unique hosts served: 2

そこで、

{
        date = substr($1,1,7)
        arr[date, $8]++
}

というのを考えてみましたが、ここから先が分かりません。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/842fd996910cc584/5f974370c872c1b9?hl=ja#5f974370c872c1b9


  • 以下を試してみてください。 - Ed Morton (2005年11月12日 20時45分24秒)
{   date = $1
     month = substr(date,1,7)
     host = $8
     hits[month]++
     monthhosts[month,host]++
}
END {
     for (month in hits) {
         numHosts = 0
         delete hosts
         for (monthhost in monthhosts) {
             split(monthhost,mhA,SUBSEP)
             host = mhA[2]
             if ((mhA[1] == month) && !(host in hosts)) {
                 hosts[host]++
                 numHosts++
             }
         }
         printf "%s total number of hits: %d\n", month, hits[month]
         printf "%s unique hosts served: %d\n", month, numHosts
     }
}

{{comment}}

perl ge and "not regexp" - Sergei Riaguzov (2005年11月11日 00時05分02秒)

  1. sed のような \N (Perl の $N) は使えますか?
  2. Perl のような ge はありますか?
s/"(reg1)(reg2)/$smth = $1 == 2 ? 2 : 1, $1 - $smth/ge

また、sed や awk の正規表現ではないものにマッチするようなことはできますか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/543ccca95f4c5cb7/d0034240813269c6?hl=ja#d0034240813269c6


  • 最後の質問は以下のようなことですか? - William James (2005年11月11日 00時08分31秒)
BEGIN {
  split( "Clasp foo open bar", a, / *(foo|bar) */ )
  print a[1], a[2]
}
  • \N に該当するものは正確にはありませんが、& が近いです。 - Ed Morton (2005年11月11日 00時09分20秒)

また、gawk の gensub() で近いことができます。

PS1> echo "abcbd" | gawk 'sub(/b/,"|&|")'
a|b|cbd
PS1> echo "abcbd" | gawk 'gsub(/b/,"|&|")'
a|b|c|b|d
PS1> echo "abcbd" | gawk '$0=gensub(/b/,"|&|","")'
a|b|cbd
PS1> echo "abcbd" | gawk '$0=gensub(/b/,"|&|","g")'
a|b|c|b|d
PS1> echo "abcbd" | gawk '$0=gensub(/(b)/,"|\\1|","")'
a|b|cbd
PS1> echo "abcbd" | gawk '$0=gensub(/(b)/,"|\\1|","g")'
a|b|c|b|d
PS1> echo "abcbd" | gawk '$0=gensub(/(b)(c)/,"|\\2\\1|","g")'
a|cb|bd

また、最後の質問は以下のようなことですか?

awk '{for (i=1;i<=NF;i++) if ($i !~ /re/) print $i}' file
  • 例えば、以下のようなことを言っています。 - Sergei Riaguzov (2005年11月12日 20時34分37秒)
#!/usr/bin/perl

$ff = "123";
$ff =~ s/(1)(23)/$var = (($1 == 1) ? 2 : 1).$2, $var/ge;
print "$ff\n";

muf@cocaine:~/ddd$ ./zz
223

また、

s/!([0-9]+)/zz/g

のようにすると、

abcd 123 bedfg 4343hh

zz 123 zz 434zz

のようになってくれるようなものを示しています。

  • 以下のようにすればできます。 - Ed Morton (2005年11月12日 20時38分09秒)
$ cat zz
#!/usr/bin/awk -f
BEGIN {
ff = 123
var = gensub(/(1)(23)/,"\\1","",ff)
ff = gensub(/(1)(23)/,(var == 1 ? 2 : 1)"\\2","",ff)
print ff
}
$ ./zz
223

また、

$ echo "abcd 123 bedfg 4343hh" | awk 'gsub(/([^0-9 ])+/,"zz")'
zz 123 zz 4343zz

のようにできます。

XML に関しては gawk に XML ライブラリがありますが、まず、なにがしたいかを明確にすることが先でしょう。

  • 最初のものは非常に複雑ですが、確かにそうなりますね。 - Sergei Riaguzov (2005年11月12日 20時40分46秒)

次のものは、欲しいものは「正規表現に該当しない」ものが欲しいのです。

{{comment}}

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


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