Just another Ruby porter,

〜2015年2月上旬〜


<Older(,) | Newer(.)> | Recent(/)>> | RDF

2015-02-01 (Sun)

【問題】第15回ドキッ!grepだらけのシェル芸勉強会 にUstで参加

今回も行けなかったのでUstで参加。

_ Q1 1という文字を含まないファイル:

grep3連発。

% seq 2 5 > a
% seq 1 9 > b
% seq 5 11 > c
% seq 3 6 > d
% grep -c 1 ? | grep 0 | grep -o '^.'
a
d

と思ったら-Lという素敵なオプションがあるなんて、びっくりですわ。

-L, --files-without-match
       Suppress normal output; instead print the name of each input file from which no output  would  normally
       have been printed.  The scanning will stop on the first match.

_ Q2 1-9, 10-90, 下2桁が00のファイルだけ残してあとを消す:

否定形なので結構悩む。

% ls | grep -Pv '\.\d$|\d0$|00$' | xargs rm

今思うと、-Pを使うまでもないな。

% ls | grep -v '\..0\?$\|00$' | xargs rm

_ Q3 -v, -f, awkの数をカウント:

最終的にはほぼ同じ。

% grep -ow 'awk\|-[vf]' text1 | sort | uniq -c  

_ Q4 /etcの下のshbangとset -eがあるファイルの数:

なんか無理矢理感満載だ。sudoのあるなしはこの際どうでもいいのでカット。

% grep -R -l '#!/bin/sh' /etc | xargs grep -c "set -e" | tee >(grep -c ':0$') | grep -c ':[^0]$'

uniq -cにしておこう。

% grep -R -l '#!/bin/sh' /etc | xargs grep -c "set -e" | awk '$0=/:0$/_' | sort | uniq -c

_ Q5 日本語やギリシャ文字のある行を除去:

ほぼ解答例と同じ。

% grep -P '^[[:print:]]*$' text2

_ Q6 ファイルの中の数字を足して10になるファイル:

grepじゃないが。

% awk '$1+$2+$3+$4==10{print FILENAME}' ?

もう1個。これもgrepじゃない。grep 10で無理矢理使えなくもないが。

% for i in ?;do read a < $i;[ $[${a// /+}] = 10 ] && echo $i;done

_ Q7 psコマンドを打って(オプションは任意)、そのpsコマンドの行、親プロセスの行、親の親のプロセスの行を表示:

パス。

_ Q8 seqとfactorの出力の後ろにgrepだけをいくつかつなげて、「素数の一つ前の数で、かつ10以上の数」を列挙してください。:

grepしばり。

$ seq 10 1000 | factor | ...(grepだけ)

grep3つで。

% seq 10 1000 | factor | grep -B1 ': [^ ]*$' | grep ': [^ ]* ' | grep -o '^[0-9]*'

Perlの正規表現の肯定先読みを使うとgrepを1個減らせる。

% seq 10 1000 | factor | grep -B1 ': [^ ]*$' | grep -Po '.*(?=: [^ ]* )'

2015-02-02 (Mon)

Q7 psコマンドを打ってご先祖さまを表示 #シェル芸

なんかいろいろいじってるうちにgrepがなくなってしまった。

% ps -eo ppid,pid,args --forest | tac | awk '(/ [p]s /||$2==pid)&&pid=_$1' | tac
    0     1 /sbin/init
    1  1216 lightdm
 1216  2076  \_ lightdm --session-child 12 15
 2076  2093      \_ upstart --user
 2093  3531          \_ tmux start-server; show-option -g
 3531 25659          |   \_ -zsh
25659  9151          |       \_ ps -eo ppid,pid,args --forest

tacを使うと素直に上から下へのスキャンで済む。
面倒なのでご先祖さまのinitまで表示。
-fと--forestは違うようだ。


2015-02-03 (Tue)

823年ぶりというデマ #シェル芸

2月のカレンダーがきれいに4段におさまっているのが823年ぶりというデマが出回った。

% cal -h
   February 2015      
Su Mo Tu We Th Fr Sa  
 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  


ではどのくらいあるのか考えてみよう。
条件としては2/1が日曜日でうるう年ではない、この2つがそろえばok。
言い変えると3/1の前日が28日で土曜日とも言える。
そうすることでdate一発で判断可能になる。

% date -d '2015-03-01 -1day' +'%F %a'         
2015-02-28 Sat
% date -d '2012-03-01 -1day' +'%F %a'
2012-02-29 Wed

'28 Sat'でgrepすればいいわけだ。以上まとめて適当に1951年から2050年の100年間で調べてみる。

% seq -f '%g-03-01 -1day' 1951 2050 | xargs -L1 -d '\n' date +'%F %a' -d | grep '28 Sat'
1953-02-28 Sat
1959-02-28 Sat
1970-02-28 Sat
1981-02-28 Sat
1987-02-28 Sat
1998-02-28 Sat
2009-02-28 Sat
2015-02-28 Sat
2026-02-28 Sat
2037-02-28 Sat
2043-02-28 Sat

前回は2009年、次回は2026年だとわかった。
見ればわかるとおり間隔は6,11,11の繰り返しになっている。


2015-02-04 (Wed)

金土日5回 #シェル芸

823年デマにはいろんパターンがあるようで。
「823年に一度の奇跡のカレンダー」の季節が今年もやってきました - 聴く耳を持たない(片方しか)

今日は金土日曜が5回ある月を探してみよう。
実は昨日の件と条件は似ていて、簡単にいうと月末が31日で日曜日になっている月となる。
つまり翌月1日の前日が31日で日曜日。これもdate一発でok。

% seq -f "2015-%g-01 1month -1day" 12 | xargs -L1 -d '\n' date "+%F %a" -d
2015-01-31 Sat
2015-02-28 Sat
2015-03-31 Tue
2015-04-30 Thu
2015-05-31 Sun
2015-06-30 Tue
2015-07-31 Fri
2015-08-31 Mon
2015-09-30 Wed
2015-10-31 Sat
2015-11-30 Mon
2015-12-31 Thu

例によって"31 Sun"でgrep。
2001年から2020年までの期間で探してみよう。

% seq 2001 2020 | xargs -i seq -f '{}-%g-01 1month -1day' 12 | xargs -L1 -d '\n' date '+%F %a' -d | grep '31 Sun'
2002-03-31 Sun
2003-08-31 Sun
2004-10-31 Sun
2005-07-31 Sun
2006-12-31 Sun
2008-08-31 Sun
2009-05-31 Sun
2010-01-31 Sun
2010-10-31 Sun
2011-07-31 Sun
2013-03-31 Sun
2014-08-31 Sun
2015-05-31 Sun
2016-01-31 Sun
2016-07-31 Sun
2017-12-31 Sun
2019-03-31 Sun
2020-05-31 Sun

今年は5月にまた823年デマが流れるかも。

% ncal -M 5 2015
    May 2015          
Mo     4 11 18 25   
Tu     5 12 19 26   
We     6 13 20 27   
Th     7 14 21 28   
Fr  1  8 15 22 29   
Sa  2  9 16 23 30   
Su  3 10 17 24 31   

2015-02-05 (Thu)

xargsで空白を含んだ引数を扱う

findの-print0のようにNULで区切られればxargs -0で受けられる。
しかしなかなかそういうオプションがあるコマンドは少ない。
tr '\n' '\0'で無理矢理という手もあるがもっと手軽な方法がある。
1行1引数にしたければ-L1 -d '\n'のようにすればok。

% echo 'a b\nc' | xargs ruby -e 'p ARGV'
["a", "b", "c"]
% echo 'a b\nc' | xargs -L1 ruby -e 'p ARGV'
["a", "b"]
["c"]
% echo 'a b\nc' | xargs -L1 -d '\n' ruby -e 'p ARGV'
["a b"]
["c"]
% echo 'a b\nc' | tr '\n' '\0' | xargs -L1 -0 ruby -e 'p ARGV'
["a b"]
["c"]

一昨日昨日の日記参照。


2015-02-06 (Fri)

virtualbox-guest-dkms

以前 virtualbox-guest-dkmsを入れた話を書いたが、
これって結局kernelが上がっても一々Guest Additionsを入れなおさなくてもいい
というものすごいうれしい副作用が。


2015-02-07 (Sat)

awkで並列処理

awkでprint | "command"とするとパイプ処理になるが、名前が違えば別の処理になる。
たとえば

% LANG=C awk '{print | "sort > file" NR%5}' file.txt & (sleep 1; ps -o pid,args -C sort); sort -m file{0..4} > q
[1] 9151
  PID COMMAND
 9160 sort
 9161 sort
 9163 sort
 9165 sort
 9166 sort

とすれば5個sortが並列に動く。
ただしこれ実際に一番CPU食うのはawkなので全然速くならない。


2015-02-08 (Sun)

落穂拾い Q7の別解

psの-Hオプションを使ってみた。

% ps -eo ppid,pid,args --forest | tac | awk '(/ [p]s /||$2==pid)&&pid=_$1' | tac
    0     1 /sbin/init
    1  1182 lightdm
 1182  2002  \_ lightdm --session-child 12 15
 2002  2016      \_ upstart --user
 2016  3030          \_ /usr/bin/xfce4-terminal
 3030  7882          |   \_ zsh
 7882 20327          |   |   \_ ps -eo ppid,pid,args --forest
% ps -eHo ppid,pid,args | tac | awk '(/ [p]s /||$2==pid)&&pid=_$1' | tac
    0     1 /sbin/init
    1  1182   lightdm
 1182  2002     lightdm --session-child 12 15
 2002  2016       upstart --user
 2016  3030         /usr/bin/xfce4-terminal
 3030  7882           zsh
 7882 21483             ps -eHo ppid,pid,args

--forestは無理矢理抜き出したので表示がいまいちだが、
余計なものがない後者のほうがいい感じ?


<Older(,) | Newer(.)> | Recent(/)>> | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!