〜2015年2月上旬〜
今回も行けなかったのでUstで参加。
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.
否定形なので結構悩む。
% ls | grep -Pv '\.\d$|\d0$|00$' | xargs rm
今思うと、-Pを使うまでもないな。
% ls | grep -v '\..0\?$\|00$' | xargs rm
最終的にはほぼ同じ。
% grep -ow 'awk\|-[vf]' text1 | sort | uniq -c
なんか無理矢理感満載だ。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
ほぼ解答例と同じ。
% grep -P '^[[:print:]]*$' text2
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
パス。
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 '.*(?=: [^ ]* )'
なんかいろいろいじってるうちに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は違うようだ。
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の繰り返しになっている。
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
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"]
以前
virtualbox-guest-dkmsを入れた話を書いたが、
これって結局kernelが上がっても一々Guest Additionsを入れなおさなくてもいい
というものすごいうれしい副作用が。
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なので全然速くならない。
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は無理矢理抜き出したので表示がいまいちだが、
余計なものがない後者のほうがいい感じ?