「Hagi utils」の版間の差分

提供: Wikinote
移動: 案内検索
(bash スクリプト)
行1: 行1:
【オレ外秘】(笑)
 
 
 
ちょっとしたコマンドやライブラリを自宅と会社で同期するためのページ。
 
ちょっとしたコマンドやライブラリを自宅と会社で同期するためのページ。
学生時代に作ってたヤツは今じゃ全然使い物にならない…。
 
  
 
== C 言語==
 
== C 言語==
行89: 行86:
  
 
== gawk スクリプト ==
 
== gawk スクリプト ==
=== maxlen コマンド ===
 
テキストファイル中の最も長い行の長さを求めるスクリプト。
 
  
ソースコード <toggledisplay>
+
== bash スクリプト ==
#!/bin/gawk -f
+
## Usage: maxlen FILE
+
## Print maximum line length of FILE
+
+
BEGIN {
+
    if (ARGC != 2) {
+
        print "Usage: maxlen FILE"
+
        exit 1
+
    }
+
}
+
{
+
    len = length()
+
    if (max < len) max = len
+
}
+
END {
+
    if (ARGC == 2) {
+
        print max
+
    }
+
}
+
</toggledisplay>
+
  
まあこれくらいインスタントに書いた方が早いですが。
+
=== split_strace.sh ===
$ gawk '{if (max < length()) max = length()}END{print max}' FILE
+
strace -f で採取したログをプロセス毎に分割する。
とか。
+
  
== bash スクリプト ==
+
#!/bin/bash
 +
 +
if [ $# -ne 2 ]; then
 +
    printf "Usage: %s LOGFILE TARGET_DIR\n" "$0"
 +
    exit 1
 +
elif [ ! -e "$2" ]; then
 +
    mkdir -p "$2"
 +
    echo INFO: directory \'$2\' is made.
 +
elif [ ! -d "$2" ]; then
 +
    echo ERROR: \'$2\' is NOT directory.
 +
    exit 1
 +
fi
 +
 +
echo collecting PIDs...
 +
PIDS=$(awk '{print $1}' "$1" | sort | uniq | sort -n)
 +
echo PIDS=$PIDS
 +
 +
for PID in $PIDS; do
 +
    echo do grep ^$PID $1
 +
    grep ^$PID "$1" > "$2/$PID"
 +
done
 +
echo done.
  
 
=== difftime ===
 
=== difftime ===

2011年3月31日 (木) 22:17時点における版

ちょっとしたコマンドやライブラリを自宅と会社で同期するためのページ。

C 言語

printb() 関数

整数を 2 進数で表示する関数。

ソースコード <toggledisplay>

#include <stdio.h>

void printb(unsigned num) {
    int i;
    for (i = 31; i >= 0; i--) {
        putchar(((num >> i) & 1) + '0');
    }
}

void printb64(unsigned long long num) {
    int i;
    for (i = 63; i >= 0; i--) {
        putchar(((num >> i) & 1) + '0');
    }
}

</toggledisplay> 使用例:argv[1]atoi() に渡して printb() にかけるコマンド

[hagio@lab ~]$ printb 1234567890
01001001100101100000001011010010
[hagio@lab ~]$ printb -1
11111111111111111111111111111111

fill コマンド

標準入力の各行を、指定された行長までスペースで埋めるコマンド。

ソースコード <toggledisplay>

#include <stdio.h>

int main(int argc, char *argv[]) {
    int max, len;
    int c;

    if (argc != 2) {
        printf("Usage: fill MAXLEN < FILE\n");
        return 1;
    }

    max = atoi(argv[1]);
    len = 0;
    while ((c = getchar()) != EOF) {
        if (c == '\n') {
            for ( ; len < max; len++) {
                putchar(' ');
            }
            putchar('\n');
            len = 0;
        }
        else {
            putchar(c);
            len++;
        }
    }
}

</toggledisplay> printf() で簡単にできた…。バッファリングバージョン。

ソースコード <toggledisplay>

#include <stdio.h>
#include <string.h>
#define MAXLEN 1024

int main(int argc, char *argv[]) {
    int max, len;
    char line[MAXLEN];

    if (argc != 2) {
        printf("Usage: fill MAXLEN < FILE\n");
        return 1;
    }
    max = atoi(argv[1]);
    while (fgets(line, MAXLEN, stdin)) {
        len = strlen(line);
        line[len-1] = '\0';
        printf("%-*s\n", max, line);
    }
}

</toggledisplay>

gawk スクリプト

bash スクリプト

split_strace.sh

strace -f で採取したログをプロセス毎に分割する。

#!/bin/bash

if [ $# -ne 2 ]; then
    printf "Usage: %s LOGFILE TARGET_DIR\n" "$0"
    exit 1
elif [ ! -e "$2" ]; then
    mkdir -p "$2"
    echo INFO: directory \'$2\' is made.
elif [ ! -d "$2" ]; then
    echo ERROR: \'$2\' is NOT directory.
    exit 1
fi

echo collecting PIDs...
PIDS=$(awk '{print $1}' "$1" | sort | uniq | sort -n)
echo PIDS=$PIDS

for PID in $PIDS; do
    echo do grep ^$PID $1
    grep ^$PID "$1" > "$2/$PID"
done
echo done.

difftime

2 つの日時の差を様々な形式で出力する。

#!/bin/bash
if [ $# -lt 2 ]; then
    echo "Usage: difftime DATE1 DATE2"
    exit 0
fi
START=$(date +%s -d "$1")
END=$(date +%s -d "$2")
SEC=$((END - START))
MIN=$(echo $SEC / 60 | bc -l)
HOUR=$(echo $SEC / 3600 | bc -l)
DAY=$(echo $SEC / 86400 | bc -l)
INT_DAY=$(echo $SEC / 86400 | bc)
REM_HOUR=$(echo $SEC % 86400 | bc)
INT_HOUR=$(echo $REM_HOUR / 3600 | bc)
REM_MIN=$(echo $REM_HOUR % 3600 | bc)
INT_MIN=$(echo $REM_MIN / 60 | bc)
INT_SEC=$(echo $REM_MIN % 60 | bc)

echo "$2 - $1"
echo "= $END - $START"
echo "= $SEC seconds"
echo "= $MIN minites"
echo "= $HOUR hours"
echo "= $DAY days"
echo "= $INT_DAY days $INT_HOUR hours $INT_MIN minutes $INT_SEC seconds"

実行例:もういくつ寝るとお正月

$ difftime "$(LANG=C date)" '1/1 0:0:0 2011'
1/1 0:0:0 2011 - Wed Oct 13 22:06:59 JST 2010
= 1293807600 - 1286975219
= 6832381 seconds
= 113873.01666666666666666666 minites
= 1897.88361111111111111111 hours
= 79.07848379629629629629 days
= 79 days 1 hours 53 minutes 1 seconds

cgrep

パターンが含まれる関数名を表示するスクリプト。ほとんど awk ですけど。

ソースコード <toggledisplay>

#!/bin/bash
IFS=$'\n'
RESULT=$(grep -nH $@) 
for l in $RESULT; do
    FILE=$(echo "$l" | cut -d: -f 1)
    LINE=$(echo "$l" | cut -d: -f 2)
    gawk -v line=$LINE -v file=$FILE '
        NR < line && /^\w/ && !/:/ {
            cand = $0
            cand_line = NR
        }
        NR == line {
            if ($0 ~ /^\w/) {
                print file ":" line ":"
            } else {
                print file ":" cand_line ":"
                print cand
            }
            gsub("\t", "    ") 
            print $0
            exit
        }
    ' $FILE
done

</toggledisplay>

addtime

ソースコード

#!/bin/bash
# addtime : add date and time to each line of standard input.
# Usage: addtime [-s] < FILE
/bin/gawk '{ print strftime("%F %T"), $0 }'
[ "$1" = "-s" ] && echo

rcat

指定されたファイルを逆順に連結するコマンド。

例えば、cat /var/log/messages* とやると messages, messages.1, messages.2, ... と最新のファイルから順に出力されるので時系列にならない。 rcat /var/log/messages* なら messages.4, messages.3, ... という順で出力されるので すべての messages を一気に時系列で見ることができる。

ソースコード

#!/bin/bash
# rcat : concatenate files reversely and print
# Usage: rcat FILES..
if [ $# -gt 0 ]; then
    cat $(ls -r "$@")
fi

既知のバグ

  • 連番が 10 以上になると順序がおかしくなる。

plog コマンド

プログラムを定期的に実行し、その出力にタイムスタンプを付与するシェルスクリプト。

Usage:
    plog [-d] [-i INTERVAL] [-n] command
    plog -h
Options:
    -d           時刻に加えて日付を付加する。
    -h           使い方を表示する。
    -i INTERVAL  コマンドを実行する間隔(秒)。デフォルトでは 1 秒。
    -n           時刻等を付加せず、コマンドの実行結果のみを出力する。

ソースコード <toggledisplay>

#!/bin/bash
### parameters ###
INTERVAL=1
PRINT_TIME=1
PRINT_DATE=0
### constants ###
CMD_NAME=$(basename $0)
DEFAULT_SCRIPT='{ print strftime("%T"), $0 }'
ADDDATE_SCRIPT='{ print strftime("%F %T"), $0 }'
### flags & variables ###
GETOPT_ERR=0

### functions ###
function usage() {
   echo "Usage:"
   echo "    $CMD_NAME [-d] [-i INTERVAL] [-n] command"
   echo "    $CMD_NAME -h"
   echo "Options:"
   echo "    -d          Print date besides time."
   echo "    -h          Print this help."
   echo "    -i INTERVAL Specify the interval between executions. (seconds) Default is 1 s."
   echo "    -n          Do not print time or date. Print command output only."
}

### main ###
while getopts "i:ndh" opt; do
   case $opt in
       i) INTERVAL=$OPTARG;;
       n) PRINT_TIME=0;;
       d) PRINT_DATE=1;;
       h) usage; exit 0;;
       ?) GETOPT_ERR=1;;
   esac
done
shift $(( $OPTIND - 1 ))

if [ $GETOPT_ERR -eq 1 -o $# -eq 0 ]; then
   usage
   exit 0
fi

CMD=$@
while : ; do
   if [ $PRINT_TIME -eq 0 ]; then
       $CMD
   elif [ $PRINT_DATE -eq 1 ]; then
       $CMD | gawk "$ADDDATE_SCRIPT"
   else
       $CMD | gawk "$DEFAULT_SCRIPT"
   fi
   sleep $INTERVAL
done

</toggledisplay>

Python スクリプト

subset.py

./subset.py SUPERSET SUBSET

で、SUBSET に含まれる SUPERSET の要素にタグをつける。

ソースコード <toggledisplay>

#!/usr/bin/env python

import sys

if len(sys.argv) != 3:
        print "Usage: %s SUPERSET SUBSET"
        sys.exit(0)

superset = file(sys.argv[1]).readlines()
subset = file(sys.argv[2]).readlines()
for super_str in superset:
       if super_str in subset:
               print super_str[:-1], "sub"
       else:
               print super_str,

</toggledisplay>

実行例 <toggledisplay>

[hagio@localhost ~]$ cat hoge
0
1
2
3
4
5
6
7
8
9
[hagio@localhost ~]$ cat hoge_sub
2
3
5
7
[hagio@localhost ~]$ ./subset.py hoge hoge_sub
0
1
2 sub
3 sub
4
5 sub
6
7 sub
8
9
[hagio@localhost ~]$

</toggledisplay>