コミュニティ/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: simple how to supply a list of fields - janvdberg (2005年12月14日 01時34分22秒)

awk '{print
$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25}'
file

ここで、7 番目から 31 番目のフィールドまでの出力をしたいのですが、

awk '{print $7-$25}' file

ではダメでした。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/b229cc7f61ecafe9/4407321f9cc07c05?hl=ja#4407321f9cc07c05


  • 以下のようにしてできます。 - Ed Morton (2005年12月14日 01時34分47秒)
awk '{for (i=7;i<=25;i++){printf "%s%s",sep,$i;sep=FS} print ""}'

また正規表現でフィールドを削除するようなこともできます。N 番目までが不要であれば、以下のようにできます。

gawk --re-interval 'sub(/^[[:space:]]*([^[:space:]]*[[:space:]]*){N}/,"")'
  • Ed のものはもう少し簡単になります。 - Kenny McCormack? (2005年12月14日 01時37分17秒)
{for (i=7;i<=25;i++) printf "%s%s",$i,i==25 ? ORS : FS}

または、

BEGIN {ORS=FS}
{for (i=7;i<25;i++) print $i;printf "%s\n",$i}

{{comment}}

providing documentation for executable - Sebastian Luque (2005年12月11日 20時46分38秒)

BEGIN で usage を表示しようとしています。

pn = "progname"
if (ARGC < 2) {
    usage(pn)
    exit 1
}

普通のプログラムと同様に、-h や --help で表示させたいのですが、どうすればいいでしょうか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/962aee6ee8f41bcf/782df0001a8ffa4c?hl=ja#782df0001a8ffa4c


  • shell スクリプトに awk を埋め込むのが楽です。 - Harlan Grove (2005年12月11日 20時47分18秒)
  • 以下のようにして使っています。 - eiso (2005年12月12日 01時09分28秒)
#!/software/bin/gawk -f
#
#@ convert protein aminoacid sequence files from
#@ oneletter to threeletter format and vice versa.
#
# (c) Eiso AB
#
# command line options:
# [-v] mode=3to1   # convert from three to one letter format
# [-v] mode=1to3   # convert from one to three letter format [ABCDE...]
# [-v] mode=1nto3  # convert from one to three letter format [A1/
#
# -h|help|--help   # print help
#
# seq2seq.awk will try to determine the type of file from the first
# field on the first line it encounters. If the first word has either
# one or 4 or more characters oneletter format will be assumed.
#
# possible input:
#

BEGIN {
    progname="seq2seq.awk"
    if ( ARGV[1]~/^([-]h|help|[-][-]help)$/ ) {
        # -h|help|--help as first argument will print all lines
starting
        # with '#' intil the first line that starts with BEGIN
        # because of the which command, help is only available if
        # this script is in the PATH
        system("gawk '/^#/{print}/^BEGIN/{exit}' `which "progname"`")
        help=1

        exit
    }
}
[...]
END { if (help==1) exit }
  • 以下のものを試してみてください。 - Ed Morton (2005年12月12日 01時11分27秒)
BEGIN {
        for (i=1;i<ARGC && ARGV[i]!="-h";i++);
        if (i != ARGC) { print "usage..."; exit }
}
  • これが求めていたものに近いのですが、awk ではループの中の変数はグローバル変数になりますか? - Sebastian Luque (2005年12月12日 22時02分18秒)
  • awk ではローカル変数として指定しないものは全てグローバル変数になります。 - Janis Papanagnou (2005年12月12日 22時03分36秒)
  • R はローカル変数として扱われますね。 - Sebastian Luque (2005年12月12日 22時05分17秒)

{{comment}}

Lines common/unique to 2 files - Sashi (2005年12月11日 20時39分40秒)

2 つのファイルがあります。これの共通な部分を抜き出すことは可能ですか?

また、ユニークなところだけを抜き出すことは可能ですか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/218de02c5dff6e1e/ab92b5236365e90f?hl=ja#ab92b5236365e90f


  • 以下のようにしてできます。 - Janis Papanagnou (2005年12月11日 20時40分17秒)
NR==FNR {f1[$0]=$0}
NR!=FNR {f2[$0]=$0}
END {
     print "Common:"
     for(i in f1) if(i in f2) print f1[i]
     print "Only in f1:"
     for(i in f1) if(!(i in f2)) print f1[i]
     print "Only in f2:"
     for(i in f2) if(!(i in f1)) print f2[i]
}
  • もっと簡単にできます。 - Janis Papanagnou (2005年12月11日 20時41分08秒)
NR==FNR {f1[$0]}
NR!=FNR {f2[$0]}
END {
     print "Common:"
     for(i in f1) if(i in f2) print i
     print "Only in f1:"
     for(i in f1) if(!(i in f2)) print i
     print "Only in f2:"
     for(i in f2) if(!(i in f1)) print i
}
  • 少し変えてみました。他にアイデアがあれば募集します。 - Loki Harfagr (2005年12月11日 20時42分42秒)
NR==FNR {f[$0]=f[$0]1}
NR!=FNR {f[$0]=f[$0]2}
END {
     print "Common:"
     for(i in f) if(match(f[i],/1/) && match(f[i],/2/) ) print i
     print "Only in f1:"
     for(i in f) if(!match(f[i],/2/) ) print i
     print "Only in f2:"
     for(i in f) if(!match(f[i],/1/) ) print i
}
  • さらに変更してみました。 - Loki Harfagr (2005年12月12日 01時06分48秒)
{f[$0]=f[$0]ARGIND}
END {
     print "Common:"
     for(i in f) if(match(f[i],/1/) && match(f[i],/2/) ) print i
     print "Only in f1:"
     for(i in f) if(!match(f[i],/2/) ) print i
     print "Only in f2:"
     for(i in f) if(!match(f[i],/1/) ) print i
}

{{comment}}

AWK programmer ? - jack.s.smith (2005年12月09日 21時42分09秒)

古い awk のプログラムを引き継いだのですが、動作しません。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/8cc49ec936bb9727/44470ad9068d3479?hl=ja#44470ad9068d3479


  • そのプログラムの URL を示すとか、もっとわかりやすく説明してください。 - Loki Harfagr (2005年12月09日 21時43分01秒)
  • スクリプトを分割して投稿するか、どこか Web サイトに掲載するのが良いと思います。 - Juergen Kahrs (2005年12月11日 20時37分15秒)

{{comment}}

gawk vs. nawk portability issue - Scotty (2005年12月07日 01時07分43秒)

gawk で split(LINE, aLINE, "") は配列 aLINE に LINE のそれぞれの文字を格納します。ところが、nawk では aLINE[1] に全てが格納されてしまいます。

FS を "" 以外にすることで同じ挙動にすることはできますか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/ddccde87242fda3c/42e9a2b2db1c7258?hl=ja#42e9a2b2db1c7258


  • gawk では FS="" の場合、全ての文字がフィールドに分割されます。 - Ed Morton (2005年12月07日 01時09分08秒)

他の awk を gawk に合わせるのは難しいですが、gawk を他の awk に合わせるのはコンパチオプションでできます。でも、もっと良いのは nawk を捨てて、gawk にすることです。

{{comment}}

list file through filter by recent date - nico (2005年12月05日 22時27分29秒)

自分の興味のある日にちだけを取得したいのです。

$2 には月が書かれてあり、$3 には日が書かれています。

while :
do
echo PROCESOS LA003 - WAVEMANAGER

# in these lines my goal is to get the second column ($2) which has the
month and the third column ($3) that has the day.
# the print month_cmp " " day_cmp is there to verify that it works fine
awk '{
   system("date |awk '{
         month_cmp = $2
         if ($3 < 10)
            { day_cmp = "0" $3 }
         else
            { day_cmp = $3 }
         print month_cmp " " day_cmp }'")
# unfortunately it never gets to the print line and most of the time
(through many modifications) i have to press enter, or sometime it just
shows errors with body parsing errors such as "}" missing or " ") " not
expected.

# in the following lines i only want to display the logs with the
month_cmp and day_cmp  gotten from the above lines - system("date | awk
.... ")
      if ($6 = month_cmp && $7 = day_cmp)
         { system("ls -ltr /u02/app/se2/del4/work/faxlp |grep
LA003a_I3") }
   }'

sleep 3
clear

done

時々、system("date | awk...") のところで止まってしまいます。スクリプトを直してもらって、グローバル変数をセットしてもらえると助かります。

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


  • system() がネストしすぎているからでしょう。 - Janis Papanagnou (2005年12月05日 22時29分14秒)
ls -ltr ... | awk -v d=$(date +%Y-%m-%d) '/LA003a_I3/ && $6==d'

のように簡単に考えてみてはどうでしょうか?

  • 少し変えてみました。 - nico (2005年12月11日 20時35分05秒)
while :
do
   echo PROCESOS LA003 - WAVEMANAGER
      ls -ltr /u02/app/se2/del4/work/faxlp | awk -v m=$(date +%b)
'/LA003a_I3/ && $6==m' > filtrar_la003.lst
      awk -v d=$(date +%d) '$7==d END { print $0 }' filtrar_la003.lst
      sleep 10
      rm -f filtrar_la003.lst
   clear
done

{{comment}}


  • スレ主が要領を得ないので、少し保留します。 - hi_saito (2005年12月14日 23時09分30秒)

Splitting a srting at the last occurance of "/" - Rob Bradford (2005年12月03日 22時04分03秒)

ファイル名からパス名を分離したいのです。

例えば、

./test

/home/scripts/test

./ または /home/scripts

test

に分けます。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/6ff282ac846494c9/34b7ed3783758ff6?hl=ja#34b7ed3783758ff6


  • それは shell の News Group に聞いた方が良いでしょう。 - Janis Papanagnou (2005年12月03日 22時05分26秒)

{{comment}}

Need some quick help here - Ramesh N (2005年12月03日 19時23分36秒)

特定のホストの FQDN を調べます。

host1toronto.plains.com

ここから host1 だけを抜き出す方法はありますか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/a0e91dc1be1f414a/15b81fb8cc4edf66?hl=ja#15b81fb8cc4edf66


  • 以下のようにします。 - Ed Morton (2005年12月03日 19時23分53秒)
$ awk
'BEGIN{inp="host1toronto.plains.com";out=inp;sub(/toronto.*/,"",out);print out}'
host1

{{comment}}

Subtraction with awk - samothyev (2005年12月03日 00時12分53秒)

上司に言われて sed と awk でプログラムすることになりました。

#phase 1
#desired output >> timestamp.log
#$machine_hostname $time_process_ran $first_log_hit $last_log_hit

# example output
# hostname        time_process_ran     $first_log_hit
$last_log_hit
# host.domain.com 23/Nov/2005:00:05:10 22/Nov/2005:22:02:04
23/Nov/2005:00:02:10  #entry 1
# host.domain.com 23/Nov/2005:00:06:10 22/Nov/2005:22:03:04
23/Nov/2005:00:06:01  #entry 2
#phase 2
# compare entry1->$last_log_hit to entry2->first_log_hit and
compare/print difference

まずは Phase 1 まで。

#!/bin/bash

acc_log="/var/log/apache/access_log"

# Get hostname
/bin/hostname >> /home/usrname/timestamp.log

# Time the process ran
ls -l $acc_log | awk '{print $6,$7,$8}' >> /home/usrname/timestamp.log

# First Log Hit
/usr/bin/head -1 $acc_log | /bin/awk '{print $4}' | /bin/sed -e
's/\[//' >> /home/usrname/timestamp.log

# Last Log Hit
/usr/bin/tail -1  $acc_log | /bin/awk '{print $4}' | /bin/sed -e
's/\[//' >> /home/usrname/timestamp.log

とすると、以下のような出力が得られます。

host.domain.com
Dec 1 17:14
01/Dec/2005:00:04:42
01/Dec/2005:17:14:12

次に Phase 2 では 4 行目から 3 行目の引き算を行う必要があります。これは可能ですか?

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/9a5ee46a4c10d8b7/6a9cae4fc42ffea2?hl=ja#6a9cae4fc42ffea2


  • どこが awk の質問なんですか? - Kenny McCormack? (2005年12月03日 00時13分37秒)
  • 17:14:00 から 00:04:00 を引いて 17:10:00 を得たいのですが、どうすればいいのでしょうか? - samothyev (2005年12月03日 00時14分41秒)
  • gawk なら mktime() を使って、エポックからの秒数にすることができます。 - Kenny McCormack? (2005年12月03日 00時15分48秒)
  • CentOS の up2date で mktime を見つけました。 - samothyev (2005年12月03日 00時18分04秒)
  • mktime は OS でもソフトでもありません。もっともパワフルな awk である gawk の一部です。 - William James (2005年12月03日 00時19分01秒)
  • 全て awk でできてしまいますよ。 - Ed Morton (2005年12月03日 19時16分48秒)

最初のヒットの部分は、

awk 'NR==1{sub(/[[]/,"",$4);print $4;exit}' "$acc_log" >>
/home/usrname/timestamp.log

最後のヒットの部分は、

awk '{sub(/[[]/,"",$4);t=$4}END{print t}' "$acc_log" >>
/home/usrname/timestamp.log

または、両方をひとつにして、

awk '{sub(/[[]/,"",$4);t=$4}NR==1{print t}END{print t}' "$acc_log" >>
/home/usrname/timestamp.log

とできます。

時間に関しては difftime.awk を試してみてください。

function cvttime(t,     a) {
         split(t,a,"[/:]")
         match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])
         a[2] = sprintf("%02d",(RSTART+2)/3)
         return( mktime(a[3]" "a[2]" "a[1]" "a[4]" "a[5]" "a[6]) )
}
BEGIN{
t1="01/Dec/2005:00:04:42"
t2="01/Dec/2005:17:14:12"
print cvttime(t2) - cvttime(t1)
}

これで、

gawk -f difftime.awk

とします。

sh にするのであれば、

gawk '
function cvttime(t,     a) {
         split(t,a,"[/:]")
         match("JanFebMarAprMayJunJulAugSepOctNovDec",a[2])
         a[2] = sprintf("%02d",(RSTART+2)/3)
         return( mktime(a[3]" "a[2]" "a[1]" "a[4]" "a[5]" "a[6]) )
}
{ sub(/[[]/,"",$4);t=$4 }
NR==1 { t1=t }
END { t2=t
    print t1
    print t2
    print cvttime(t2) - cvttime(t1)
}' "$acc_log" >> /home/usrname/timestamp.log

とします。

{{comment}}

Moving my AWK script from SGI to LINUX - Zeppyjnr (2005年12月02日 23時51分36秒)

SGI から Linux に awk スクリプトを移動させたら動作しなくなってしまいました。

コンパチビリティのない場合の理由が書かれたドキュメントはありますか?

if(spin_table == "")spin_table=input(workfile,"Spin table name","")

という部分が動作しません。

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


  • imput() が原因だと思われますが、これは何でしょうか? - Kenny McCormack? (2005年12月02日 23時53分17秒)
  • 以下のようなプログラムを使っていました。 - Zeppyjnr (2005年12月02日 23時54分52秒)
set funiq=/file.spin
set OFL=/file_seq_link_spin5.lst
set OFF=/file_seq_frag_spin5.lst
set OS=/tmp.spin
set fambg="/empty.txt"
set fseq=/file.seq

/asd/asdafsa/awk/seq_link_un.awk spin_table="$funiq $fambg" dltca=0.3 \
dltcb=0.4 dltco=0.3 sequence_name=$fseq fspin=$OS empty.txt | tee $OFL
/asd/asdafsa/awk/linkunq.awk debug=1 minlen=1 fout=$OFF.frag \
linkflag=1 ignoreamb=1 printall=1 $OFL | tee $OFF
date
exit

seq_link_un.awk は以下のようなものです。

#!/usr/bin/awk -f
#   dltcb=0.5
#   dltca=0.3
#   dltco=0.3
#   dlth=0.03
#   dltn=0.3
#   fspin="seq_link_un.lst"
#      showtype = show residue type flag [1]
#      showlink = show spin link flag [1]
#      typedlt  = residue type limits +- delta [1]
# linkfunpower  = Power to be used on the link deviation function [1]
#   linkshift   = shift on link function return value [0]
# make line numbering for Felix dba sequential
#
BEGIN {
      a_tl[1]=50.0; a_tu[1]=55.0; b_tl[1]=16.0; b_tu[1]=22.0; n_t[1]="A"
    ### Get process number to open unique shell file
"echo $$" | getline workfile
workfile = workfile ".tmp"
workfile1 = workfile "1"
system("echo " workfile " temporary file for seq_link_un.awk >"
workfile)
getline i < workfile
### get parameters
    if(dltcb=="") dltcb=0.5
    if(dltca=="") dltca=0.3
    if(dltco=="") dltco=0.3
    if(dlth=="") dlth=0.03
    if(dltn=="") dltn=0.3
    if(fspin=="") fspin="seq_link_un.spin"
    if(showtype=="") showtype=1
    if(showlink=="") showlink=1
    if(typedlt=="") typedlt=1
    if(linkfunpower=="") linkfunpower=1
    if(linkshift=="") linkshift=0
      if(spin_table == "")spin_table=input(workfile,"Spin table
name","")
      if(sequence_name == "")sequence_name=input(workfile,"Sequence
file name","")
    dba_cnt=1
    mxcol=10

必ず、

if(spin_table =="")spin_table=input(workfile,"Spin table name","")

でハングしてしまいます。

  • まず、 - Ed Morton (2005年12月03日 00時00分47秒)
  1. input() を見せてください。
  2. getline を使うのをやめましょう。

input() を使っているのであれば、どこかに input() を定義してあるはずですし、してなければ、undefined function でエラーになるはずです。

spin_table="$funiq $fambg"

をセットして、

if(spin_table == "")spin_table=input(workfile,"Spin table name","")

とすれば、このままでは input() が定義されていないはずです。

  • もっと簡単にできませんか? - Juergen Kahrs (2005年12月03日 00時06分08秒)
  • SGI の csh と Linux の bash の set の部分を見せてくれませんか? - Matt (2005年12月03日 19時15分18秒)

それぞれで微妙に異なります。{{comment}}

strange bug in gawk - Rolf Sander (2005年12月01日 22時44分00秒)

gawk 'BEGIN {print match("X","[^a-z]")}'

とすると 1 のはずなのに一部の OS では 0 を返します。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/d7459b208b630a97/8fb41f37f3ab1fbe?hl=ja#8fb41f37f3ab1fbe


  • これはバグとは思っていません。 - Lars Kellogg-Stedman (2005年12月01日 22時45分29秒)

ロケールの違いで異なった文字として認識されているのではないでしょうか?

 $ LC_COLLATE=C gawk 'BEGIN {print match("X","[^a-z]")}'
 1
 $ LC_COLLATE=en_US gawk 'BEGIN {print match("X","[^a-z]")}'
 0
  • 以下のようになりました。 - Rolf Sander (2005年12月02日 23時38分08秒)
linux    gawk      LC_COLLATE
system   version   C    en_US

SuSE9.1  3.1.3     1      1
Fedora   3.1.3     1      0
SuSE9.2  3.1.4     1      1

SuSe?gawk が en_US を無視させることはできますか?

  • /usr/lib/locale/en_US がありますか? - Lars Kellogg-Stedman (2005年12月02日 23時39分59秒)
  • SuSE 8.2 ではもっと面白いことになっています。 - Janis Papanagnou (2005年12月02日 23時43分26秒)
% awk --version
GNU Awk 3.1.1

% echo $LC_COLLATE
POSIX
% gawk 'BEGIN {print match("X","[^a-z]")}'
1
% LC_COLLATE=  gawk 'BEGIN {print match("X","[^a-z]")}'
0
% LC_COLLATE=C gawk 'BEGIN {print match("X","[^a-z]")}'
1
% LC_COLLATE=en_US gawk 'BEGIN {print match("X","[^a-z]">
0

LANG, LANGUAGE, LC 関係でどうなっているかで異なってきそうです。

  • これはバグではなく仕様ではないでしょうか。 - Rolf Sander (2005年12月09日 21時37分06秒)
  • LC_ALL=C だと何も心配することはありません。 - Kenny McCormack? (2005年12月09日 21時38分03秒)

{{comment}}


  • ちなみに Debian GNU/Linux では 1 を示します。 - hi_saito (2005年12月02日 23時45分55秒)

Announcement: Release of (X)Emacs CC Mode 5.31 - Alan Mackenzie (2005年12月01日 22時41分43秒)

CC Mode Version 5.31 がリリースされました。

CC Mode は AWK にも使われています。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/e086397faab292c8/08cf7d50560624d3?hl=ja#08cf7d50560624d3


{{comment}}

problems with number (int) - chrishunnell (2005年11月30日 23時55分27秒)

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

110;a
110;b
131;b
131;c
132;b
132;c
133;b
133;c
...
139;b
139;c
1310;b
1310;c
1311;b
1311;c
140;c
140;d

ここで欲しいのは以下の部分です。

110;a
131;b
140;c
140;d

グラフにしたければ、以下のようにします。

*-*=*-*

1 つのアスタリスクから他のアスタリスクへ行き、時々 = (2 つの平行線) となります。

*-*-*-*

10 の平行線以下は解決しましたが、10 以上が解けません。

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


  • 以下のようにしてできます。 - news.t-online.de (2005年12月01日 22時39分05秒)
BEGIN{
   FS=";"
}
{
   if(!($2 in FIRSTREFERRED) && ( ! ($1 in OCCURRED))  ){
       FIRSTREFERRED[$2]=$1
       OCCURRED[$1]=$2
       print $1";"$2
   }
}

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

110;a
131;b
132;c
...;
140;d

{{comment}}


  • 何が言いたいのか分からないのですが…。(苦笑) - hi_saito (2005年11月30日 23時55分49秒)

Emulation of gnu grep's -N option - James (2005年11月30日 23時46分25秒)

grep の -N オプションを awk でやりたいのです。つまり、マッチした前後の N 行を出力するのです。

grep -3 string file

こんな風にです。

grep がインストールされていない環境では非常に役立つと思うのですが、いかがでしょうか。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/0442ecd6c881969a/65f89962b5e7570d?hl=ja#65f89962b5e7570d


  • 以下のようにしてできます。これは -N と同様です。 - Ed Morton (2005年11月30日 23時47分24秒)
function nextIdx(idx) { return ( (idx % bufSize) + 1) }

function saveBuf(txt) { idx = nextIdx(idx); buf[idx] = txt }

function prtBuf() {
         for (i=0; i<bufSize; i++) {
                 j = nextIdx(idx + i)
                 if (j in buf) print buf[j]
         }
}

BEGIN{ bufSize = B + 1 }

{ saveBuf($0) }

found { found--; print }

$0 ~ pat { found = A; prtBuf() }

これを buf.awk として保存して、

awk -v pat="foo" -v A=3 -v B=2 file

のように使います。マッチした前 2 行、後 3 行を出力します。

  • 少し変えてみました。 - James (2005年12月02日 23時34分46秒)

Usage: awk -v pat="foo" -v N=3 -f script.awk file

で、

function nextIdx(idx) { return ( (idx % bufSize) + 1) }
function saveBuf(txt) { idx = nextIdx(idx); buf[idx] = txt; nr[idx] =
NR }
function prtBuf() {
        for (i=0; i<bufSize - 1; i++) {
                j = nextIdx(idx + i)
                if (j in buf) print nr[j], ": ", buf[j]
        }
        print NR, "->", $0
}

BEGIN{ A = B = N; bufSize = B + 1 }

! found { saveBuf($0) }
found && $0 !~ pat { found--; print NR, ": ", $0 }
$0 ~ pat { found = A; prtBuf(); delete buf }

としました。

{{comment}}

Extract several fields from duplicate lines - jonhardt (2005年11月30日 23時43分11秒)

Memory Size: 1024 MB

といった行があり、これを 1024 MB だけ取り出したいのです。

MEM_SIZE=`awk '/Memory Size:/ { print $3 " " $4 }' $INPUT_FILE`

ところが、

1024 MB1024 MB1024 MB1024 MB

となります。

欲しい Memory Size: という部分は最初の 1 箇所です。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/39dc99ae18576995/86ae02dc87b30132?hl=ja#86ae02dc87b30132


  • 以下のようにしてできます。 - Janis Papanagnou (2005年11月30日 23時43分33秒)
MEM_SIZE=`awk '/Memory Size:/ { print $3 " " $4 ; exit }' $INPUT_FILE`

{{comment}}

pipe as field separator - ramaka (2005年11月29日 01時39分48秒)

普通はフィールドセパレーターは ";" ですが、SAP からダウンロードしたものはパイプに変更されています。

---------------------------------------------------------
|  InvBeleg  |Pos|Material          |Charge
---------------------------------------------------------
|  10051361  |  1|1201247           |
|  10051361  |  2|1202863           |
|  10051361  |  3|1204823           |

フィールドセパレーターを "|" に変更したけどうまく動作しません。

gsub ( "|" , ";" ,?0)

としても動作しません。

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


  • どう動作しないのかを書いてください。 - Kenny McCormack? (2005年11月29日 01時40分26秒)
  • どうしようとして、何が動作しないのかを書いてください。 - Chris F.A. Johnson (2005年11月29日 01時41分02秒)
  • 以下を試してください。 - Ed Morton (2005年11月29日 01時41分20秒)
awk 'BGIN{FS="|";OFS=";'}$1=$1' file

これでうまくいかないなら、OS やファイルを書いてください。

  • 以下の間違いです。 - Ed Morton (2005年11月29日 01時42分57秒)
awk 'BGIN{FS="|";OFS=";"}$1=$1' file
  • 間違っていますね。 - Loki Harfagr (2005年11月29日 22時15分45秒)
s/BGIN/BEGIN/
  • 以下のようにします。 - news.t-online.de (2005年11月29日 22時17分53秒)
BEGIN{
    FS="[ ]*[|][ ]*"
}
NR>3{ #we don not want to see the 4 line header
    print $1
    print "InvBeleg: " $2
    print "Pos: " $3
    print "Material: " $4
    print "Charge: " $5
}

すると、

InvBeleg: 10051361
Pos: 1
Material: 1201247
Charge:

InvBeleg: 10051361
Pos: 2
Material: 1202863
Charge:

InvBeleg: 10051361
Pos: 3
Material: 1204823
Charge:

となります。

  • 以下のように FS をした方が良いでしょう。 - William James (2005年11月29日 22時19分19秒)
FS="[ \t]*[|][ \t]*"
  • awk なんだから、sub(/BGIN/,"BEGIN") と書こうよ。 - E. Rosten (2005年11月30日 01時14分17秒)

{{comment}}

system call hangs after getline - caribou (2005年11月28日 21時55分07秒)

設定ファイルを読み込んで、shell スクリプトを作成し実行するスクリプトがあります。全てインタラクティブに行うと実行可能です。

while (choice !~ /^[qQ]$/)
  {
     uiPrintPrompt()
     getline choice
     if ( choice ~ /^[lL]$/){
         cmd = getListCommand(conffile)
         exitStatus = system(cmd)
          if (exitStatus == 0){
                 printf("%s\n ", OK)
              } else {
                 printf("%s\n ", ERROR)
              }
     } else if ( choice ~ /^[ru]$/){
        # remote cvs update
        cmd=getRemoteUpdateCommand(conffile)
        exitStatus = system(cmd)
         if (exitStatus == 0){
                 printf("%s\n ", OK)
              } else {
                 printf("%s\n ", ERROR)
              }
     .....
     }
  }

ひとつは ssh を使って、

ssh -l my_user remote_machine 'cd my_dir; cvs update'

のようにします。

これだけが shell からであれば動作しますが、awk からだと動作しません。

BEGIN {
  command="ssh -l my_user remote_machine 'cd my_dir; cvs update'"
  exitStatus = system(command)
  if (exitStatus == 0){
     printf("OK\n ")
  } else {
      printf("ERROR\n ")
  }
}

これはうまく行きますが、getline の後だとハングアップします。

BEGIN {
  command="ssh -l my_user remote_machine 'cd my_dir; cvs update'"
  getline dummy
  exitStatus = system(command)
  if (exitStatus == 0){
     printf("OK\n ")
  } else {
     printf("ERROR\n ")
  }
}

リターンを押した後に無反応になります。

http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/398355c95fc5f56c/827b89541cb9e870?hl=ja#827b89541cb9e870


  • awk のトピックスではないので、まず man ssh を読んでください。 - Kenny McCormack? (2005年11月29日 01時31分25秒)

{{comment}}

Testing for AWK Scripts - becks007 (2005年11月28日 21時48分20秒)

awk のスクリプトをテストするツールはありますか?

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


  • あなたのスクリプトをテストする最適なツールが以下の場所にあります。 - Kenny McCormack? (2005年11月28日 21時49分05秒)
  • Google で awk デバッガが見つかりました。 - Manuel Collado (2005年11月30日 01時12分37秒)

{{comment}}

replace only the first occurrence of each paragraph - ibmichuco (2005年11月26日 19時45分48秒)

それぞれの段落で最初の文字列だけを置換しようとしています。

awk -v RS="" 'NR==1,/old/{sub(/old/,"new")}1;{print " "}'  filename

空行で区切られた段落を用いていますが、これで動作しますか?


http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/6f2c062c13e2af20/89b1f3f233573416?hl=ja#89b1f3f233573416

  • NR==1 は必要ないでしょう。 - Janis Papanagnou (2005年11月26日 19時46分21秒)
BEGIN { RS=""; FS="\n" }
{ sub(/old/,"new") } 1
{ print "" }

{{comment}}

nth day of the year? - Gernot Frisch (2005年11月24日 23時30分31秒)

今日が一年で何日目かを知る方法はありますか?


http://groups.google.co.jp/group/comp.lang.awk/browse_thread/thread/dfc89c7f54a11a57/52e84d740b6b4b71?hl=ja#52e84d740b6b4b71

  • GNU date でできます。 - Janis Papanagnou (2005年11月24日 23時30分58秒)
$ date +%j -d"24-nov-2005"
328
  • awk でやるんでしたね。 - Janis Papanagnou (2005年11月24日 23時31分56秒)
BEGIN{d="24-nov-2005"; "date +%j -d"d | getline day; print day}
  • 純粋に (g)awk でできますか? - Gernot Frisch (2005年11月24日 23時32分36秒)
  • gawk の mktime() や strftime() を使ったことはないのですが、多分こんな感じでしょう。 - Janis Papanagnou (2005年11月24日 23時33分42秒)
BEGIN{d="2005 11 24 0 0 0"; print strftime("%j", mktime(d))}

ちゃんと動きますね。

  • これで動作しますね。 - Gernot Frisch (2005年11月24日 23時34分29秒)
BEGIN{print strftime("%j", systime())}
  • awk を使うまでもないですよ。 - Michael Heiming (2005年11月24日 23時35分11秒)
$ date -d '24-nov-2005' +%j
328
  • 今日ならもっと簡単にできます。 - Michael Heiming (2005年11月24日 23時35分49秒)
date +%j
  • 以下のもので十分です。 - Ted Davis (2005年11月26日 19時41分44秒)
BEGIN{print strftime("%j")}

2 番目の引数が省略されれば、systime() が用いられます。

  • GNU のものであれば、以下のようにできます。 - Sashi (2005年12月01日 22時37分51秒)
awk 'BEGIN{system( "date +%j");exit}'
  • GNU awk であれば、以下のようにします。 - Kenny McCormack? (2006年01月04日 00時12分10秒)
BEGIN { print "This is day #",strftime("%j") }
  • 以下のようにできます。 - Alan Linton (2006年01月04日 21時58分06秒)
function dayofyear(y,m,d) {
  return julian(y,m,d)-julian(y,1,1)+1
}

function julian (y,m,d,hr,min,sec,  A,B,C,D,ymd) {
#convert a calendar date & time to a Julian date
#Ref. Practical Astronomy With Your Calculator, 3rd Edition
#by Peter Duffett-Smith
#julian(-4712,1,1,12)==0; 4713 BC January 1, mid-day
#julian(1985,2,17,6)== 2446113.75000000
#julian(1990,0,0)==julian(1989,12,31)==2447891.5

  d = d + (hr + (min + sec / 60) / 60) / 24
  if (m < 1) m = 1
  if (m < 3) {
    y = y - 1
    m = m + 12
  }
  ymd = sprintf("%d%02d%02d", y, m, d)
  if (ymd >= 15821015) {
    A = int(y / 100)
    B = 2 - A + int(A / 4)
  } else {
    B = 0
  }
  if (y < 0) {
    C = int((365.25 * y) - 0.75)
  } else {
    C = int(365.25 * y)
  }
  D = int(30.6001 * (m + 1))
  return sprintf("%f", B + C + D + d + 1720994.5)

}

これは gawk や UNIX 環境に依存しません。

  • 以下のような dayOfYear?() 関数を使ってできます。 - Chris F.A. Johns (2006年01月05日 22時50分26秒)

dayOfYear?() の引数は ISO 形式で 2005-11-24 のようなものです。

function dayOfYear(date) {
     m[2]  =  31;   m[3]  =  59;    m[4]  = 90
     m[5]  = 120;   m[6]  = 151;    m[7]  = 181
     m[8]  = 212;   m[9]  = 243;    m[10] = 273
     m[11] = 304;   m[12] = 334
     split( date, ymd, "-" )
     if ( ymd[2] > 2 )
        return m[ymd[2]+0] + ymd[3] + isLeapYear(ymd[1])
     else
        return m[ymd[2+0]] + ymd[3]
}

function isLeapYear(year) {
     if ( year %   4 != 0 ) return 0
     if ( year % 400 == 0 ) return 1
     if ( year % 100 == 0 ) return 0
     return 1
}

{{comment}}

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


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