コピペコードで快適生活

明日使えるソースを自分のために

第38回҈҈҉҈҈҉シ҈҉ェ҈҉ル҈҉芸҈҉勉҈҉強҈҉会メモ

https://b.ueda.tech/?post=shellgei_38 より学んだことメモ

xxd コマンド

対象を16進数でダンプする/16進数から復元する。
pオプションはpostscript形式でダンプするの意味。

# ダンプする
echo "ほげほげ" | xxd -p

# 復元する 
echo "ほげほげ" | xxd -p | xxd -r -p

# もやもやの文字コード
echo d288 | xxd -r -p
echo d289 | xxd -r -p

grep -o オプション

マッチした行ではなくマッチした箇所のみを返す

# なのでこうすれば縦に並ぶ
echo "あいうえお" | grep -o .

grep -f オプション

検索条件を保存したファイルでフィルターする

cat cond.txt
あ
い

echo "あいうえお" | grep -o . | grep -f cond.txt
あ
い

# リダイレクションと組み合わせる
cat cond.txt
あいうえお

echo "あいうえお" | grep -o . | grep -f <(grep -o . cond.txt)
あ
い

sort -kオプション

# 2項目目以降でソート
cat sample.txt | sort -k 2

# 2項目目だけでソート
cat sample.txt | sort -k 2,2

# 1項目目だけを数値としてソート
cat sample.txt | sort -k 1,1n

uniqで重複を抽出する

重複行の抽出する

# dオプションで重複のみ抽出
# fオプションで重複チェック除外フィールドを指定 (1を指定した場合は2以降で重複チェック)
cat sample.txt | sort -k 2,2 | uniq -d -f 1

trコマンド

# 置き換え(文字数は揃える必要がある)
echo 012 | gtr 012 abc

# 大文字小文字変換
echo ABC | gtr A-Z a-z

# 改行コードに変換
echo "A B C" | gtr ' ' \\n

# 指定文字以外を削除する
echo "1234567890abcdef" | gtr -dc 1234567890

nlコマンド

行数を表示

echo "A B C" | tr ' ' \\n | nl

foldコマンド

指定した幅で改行する

echo "ABCDEFGHIJK" | gfold -b5

ガウス分布な乱数生成

※0-1間の一様乱数を12回足して6引いた値の集合は、標準偏差1のガウス分布に従う。
http://www.geocities.jp/jun930/etc/varianceofrandom.html
https://bellcurve.jp/statistics/blog/17953.html

cat /dev/urandom | gtr -dc 0-9 | gfold -b10 | gsed 's/^/0./' |
gawk '{a+=$1}NR%12==0{print (a-6);a=0}'

指定範囲の文字を全部出力

echo {A..Z}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

カンマのところで改行を入れる

cat sample.txt | gsed -e "s/,/,\\n/g"

nkf(NetworkKanjiFilter)

文字コード/改行コードの変換を行うコマンド

# -w UTF8に変換
# -Lu LFに変換
# -x 半角カタカナを半角のまま
cat myoho_shinji.txt | nkf -wLux

xargsで、引数の数を指定する

cat hogefuga.txt
hoge
fuga

cat hogefuga.txt | xargs -n 2
hoge fuga

awkの中で、コマンドの実行結果を得る

# コマンド | getline 変数 で、
# 変数にコマンドの実行結果が入る
cat data.txt | gawk '{"hostname" | getline x; print x;}'
suzukake.local
suzukake.local
suzukake.local
suzukake.local

awkでバッファを出力する

fflush();

factorコマンドで素因数分解する

gfactor 12
12: 2 2 3

Q7分解

a^2 + b^2がab + 1で割り切れる正の整数の組合せa,bを生成してください(ランダムで良いです)。また、このとき、(a^2+b^2)/(ab+1)が正の整数の二乗になっていることを確かめてください。

awkを分解して見てみれば怖くない。

cat /dev/urandom | gtr -dc 0-9 | gfold -b2 | gsed 's/^0*//' | xargs -n 2 |
gawk '
($1*$1 + $2*$2) % ($1*$2+1) == 0 { # この条件に該当した場合に{}内を実行する
  a = ($1*$1 + $2*$2)/($1*$2+1); # 変数代入
  "gfactor " a | getline x ; # factorコマンドで素因数分解した結果を変数xに格納する
  print $1,$2,x; # 出力
  fflush() # バッファ出力
}
' | # 4 64 16: 2 2 2 2 のように右辺に素因数分解した結果が出力される
gawk '{
  for(i=4;i<=NF;i++) a[$i]++; # $iでi番目の値が取れる。上記の例でいうと、a[2]に4が入る。
  printf $1" "$2" "$3;
  x="OK";
  for(k in a){
    if(a[k]%2 == 1) x="NG"; # 同じ値が2で割り切れない数繰り返された = 二乗にならない場合
  }
  print x;
}'

Q8分解

数列x_{i+1} = a * x_i * (1 - x_i)について、xの初期値を0.5としてAWKで出力して、百万回以上連続で、これまで出てきていない数字を出力してください。ただし、aは3以上、4未満の小数から選んでください。これに飽き足らない人は限界に挑戦してください。

これも何やっているか分解して考えれば怖くない。

cat /dev/urandom | gtr -dc 0-9 | gfold -b10 | gsed 's/^/0./' | # 0.xの数値をランダムに出す
gawk '{print $1*4}' | gawk '$1>=3' | # 3以上4未満に揃える
while read a ; # 入力がある限り繰り返す
do
  gawk -v a=$a ' # シェル変数をawkの変数に代入
  BEGIN{
    OFMT="%.20f"; # 小数表示20桁とする(デフォだと指数表示になるため)
    x=0.5; # 数列の初期値を設定
    while(1){
      print x; # 数列の値を出力
      x=a*x*(1-x) # 数列の次の値を計算
    }
  }
  ' |
  head -n 1000000 | # 百万行出力
  sort -u | # 重複を削除して並び替え
  wc -l | # それが何行あるか
  gawk -v a=$a '
    $1==1000000 { # 百万行あれば
      print a,$1  # 出力する
    }
  ';
done |
head -n 1