【シェルスクリプトをオフィス業務の主役に!】シェルスクリプトでエクセル作業を効率化する超活用術まとめ


※ 当ページには【広告/PR】を含む場合があります。
2021/04/20
2024/01/06
シェルスクリプトでエクセル作業を効率化する超活用術まとめ
目次

ここでは当サイトで扱ったシェルコマンドの小技を取りまとめたまとめ記事です。

当サイトではオフィス業務のComputer-Aidedなハイブリッドな方法を模索し、より効率的なExcel業務を実現したい多忙なオフィスワーカー向けの主にAwkとSedを使うシェル講座です。

シェルスクリプトはどこでもどんなOSでも基本的に使えて、しかも一度使い方を覚えると、Excelと組み合わせて最高に効率の良いオフィスワークツールが作れることでしょう。

なお、シェルスクリプトはデータ(CSV)を集計することが得意ですが、人間の目で見やすくまとめることには向いていませんので、最後は人の手でまとめることには変わりありません。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

はじめに

厳しめの会社によってはセキュリティの観点からオフィスワークで使うソフトウェアは、基本的にMicrosoft Officeのスイート製品しかインストールを認められていないかもしれません。

「Excel以外の便利なソフトウェアをそう易易と会社のPCにインストールさせてもらえない!」と嘆いていらっしゃる方は、パソコンに標準装備しているシェルコマンドを使うだけでも、使いどころによってがどんな便利なツールより強力な集計/文字列/検索などの処理ができるようになるのです。

もちろん、そのためにはシェルスクリプトの扱いに慣れておく必要があります。

そこでこのブログでは、
「オフィスワークで使えるシェルコマンドでできる便利な小技」を気が向いたときに紹介していき、快適なオフィス業務作りを提案します。

なお、MacOSやLinuxであれば言わずもがな(Linuxベースの)シェルコマンドは標準で使えるのですが、Windowsの場合は「PowerShell」が標準のコンソールですので、シェルコマンドと微妙に文法と作法が異なります。

この差異を埋めるための
「busybox」という軽量プログラムをインストールすることでシェルコマンドを簡単導入できます。

合同会社タコスキングダム|蛸壺の技術ブログ
WindowsでもLinuxシェルスクリプトをいつでも簡単に使いたい!と思い立ったときの魔法のツール・busybox

Windowsコンソール端末でもLinuxのコマンドを簡単に利用できる環境が導入できるbusyboxを紹介します。

「PowerShell」が劣っているというわけではないのですが、このブログ内に限ってはWindowsユーザーには「busybox」のご利用を推奨しています。

さて、以降の各項目で、これまでのブログ記事のダイジェストをテーマ別にまとめていきます。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

基本テクニック① 〜 文字列の操作

まずは土台となるシェルコマンドの基本の話を取り扱った記事を紹介していきます。

AwkとJqの正規表現の使い方

👇最低限覚えておきたい使える正規表現の活用法

            
            ・Awkの正規表現の使い方を知りたい
・Jqの正規表現の使い方を知りたい
        
            
            $ awk '$1 ~ /[0-9]$/ {print FNR ": " $1}' << EOF
1234
abc
dfgh
567
ij
EOF
#👇出力
1: 1234
4: 567

$jq -sR '[
    split("\\r?\\n"; "g")[]|select(length > 0)|split(","; "g")
]' << EOF
2021/04/06,出張,山田
2021/04/08,会議,佐藤
2021/04/17,リモートワーク,鈴木
EOF
#👇出力
[
  [
    "2021/04/06",
    "出張",
    "山田"
  ],
  [
    "2021/04/08",
    "会議",
    "佐藤"
  ],
  [
    "2021/04/17",
    "リモートワーク",
    "鈴木"
  ]
        

AwkとJqで文字列の置換を比較

👇CSVファイルで読み出した文字列を複雑なルールで置換したい

            
            ・Awkで文字列の置換を基礎を知りたい
・Jqで文字列の置換を基礎を知りたい
        

            
            $ awk -F"," 'BEGIN {OFS=","}
{
    gsub("/", "-", $1);
    print $1, $2, $3;
}' << EOF
2021/04/06,出張,山田
2021/04/08,会議,佐藤
2021/04/17,リモートワーク,鈴木
EOF
#👇出力
2021-04-06,出張,山田
2021-04-08,会議,佐藤
2021-04-17,リモートワーク,鈴木

$ jq -sR '
    [split("\n")[]|select(length > 0)|split(",")]
    | map(.[0] |= gsub("/"; "-"))
    | map({"日付": .[0], "予定": .[1], "担当": .[2]})
' << EOF
2021/04/06,出張,山田
2021/04/08,会議,佐藤
2021/04/17,リモートワーク,鈴木
EOF
#👇出力
[
  {
    "日付": "2021-04-06",
    "予定": "出張",
    "担当": "山田"
  },
  {
    "日付": "2021-04-08",
    "予定": "会議",
    "担当": "佐藤"
  },
  {
    "日付": "2021-04-17",
    "予定": "リモートワーク",
    "担当": "鈴木"
  }
]
        

AwkとJqでCSV形式のデータを出力

👇複数の条件による検索して結果をCSVで返す

            
            ・Awkで出力フォーマットを操作したい
・Jqで出力フォーマットを操作したい
        
            
            $ awk -F"," '{
    num = match($3, /(山田|.?郎)/);
    print RSTART " " RLENGTH;
    print $0 " -> " $3 "が" num "バイト目に見つかりました";
}' << EOF
2021/04/06,出張,山田 モフ男
2021/04/08,会議,佐藤 ピヨ子
2021/04/17,リモートワーク,鈴木 フガ郎
EOF
#👇出力
1 6
2021/04/06,出張,山田 モフ男 -> 山田 モフ男が1バイト目に見つかりました
0 -1
2021/04/08,会議,佐藤 ピヨ子 -> 佐藤 ピヨ子が0バイト目に見つかりました
11 6
2021/04/17,リモートワーク,鈴木 フガ郎 -> 鈴木 フガ郎が11バイト目に見つかりました

$ jq -sR '
    [ split("\n")[] | select(length > 0) | split(",") ]
    | to_entries
    | map({date: .value[0], task: .value[1], name: .value[2], index: .key})
    | map(select(.name | test("(山田|.?郎)")))
' << EOF
2021/04/06,出張,山田 モフ男
2021/04/08,会議,佐藤 ピヨ子
2021/04/17,リモートワーク,鈴木 フガ郎
EOF
#👇出力
[
  {
    "date": "2021/04/06",
    "task": "出張",
    "name": "山田 モフ男",
    "index": 0
  },
  {
    "date": "2021/04/17",
    "task": "リモートワーク",
    "name": "鈴木 フガ郎",
    "index": 2
  }
]
        

AwkとJqで正規表現のマッチングと後方参照

👇文字列の後方参照を理解する

            
            ・Awkの正規表現でマッチした文字列をキャプチャしたい
・Jqの正規表現でマッチした文字列をキャプチャしたい
        

            
            $ awk -F"," 'BEGIN {OFS=","} {
    last4digits_ = gensub(/[0-9]{4}-[0-9]{4}-[0-9]{4}-([0-9]{4})/, "\\1", g, $2);
    print $1, last4digits_;
}' << EOF
グルヤマ マムオ,1111-2222-3333-4444,000
ヌルタニ ポウスケ,5555-5555-6666-6666,222
ポロクチ ニャルミ,3333-4444-5555-9999,777
EOF
#👇出力
グルヤマ マムオ,4444
ヌルタニ ポウスケ,6666
ポロクチ ニャルミ,9999

$ jq -sR '[ split("\n")[] | select(length > 0) | split(",") ] |
    map({
        "名義": .[0],
        "下4桁": .[1] | capture("[0-9]{4}-[0-9]{4}-[0-9]{4}-(?<digits>[0-9]{4})") | .digits
    })
' << EOF
グルヤマ マムオ,1111-2222-3333-4444,000
ヌルタニ ポウスケ,5555-5555-6666-6666,222
ポロクチ ニャルミ,3333-4444-5555-9999,777
EOF
#👇出力
[
  {
    "名義": "グルヤマ マムオ",
    "下4桁": "4444"
  },
  {
    "名義": "ヌルタニ ポウスケ",
    "下4桁": "6666"
  },
  {
    "名義": "ポロクチ ニャルミ",
    "下4桁": "9999"
  }
]
        

シェルスクリプトのパラメーター拡張で簡単な文字列操作

👇Bashの文字列のパラメーター拡張

            
            ・bashのパラメーター拡張を知りたい
・できるだけ簡潔なシェルスクリプトを書きたい
        

            
            $ HOGE_FILE="/path/to/hoge.piyo.fuga.mofu"
$ echo "${HOGE_FILE/./-}"
/path/to/hoge-piyo.fuga.mofu
$ echo "${HOGE_FILE//./-}"
/path/to/hoge-piyo-fuga-mofu
        

AwkとJqで文字列分割に必須なsplit関数の使い方

👇文字列の分割を極める

            
            ・Awkで文字列をさらに細かく分割したい
・Jqで文字列をさらに細かく分割したい
        

            
            $ awk -F"&" 'BEGIN{ OFS="," } {
    print $1,$2,$3,$4;
}' testdata.asv
#👇Csvで出力
山下モゲ雄,営業部,本社,3年
島田フガ子,経理部,名古屋支部,15年
岡田ピポ太,製造部,山口工場,8年
沢口モフ代,人事部,本社,4年
銭形ガメ吉,海外部,メキシコ支部,11年

$ jq -s -R '
    [ split("\n")[] | select(length > 0) | split(" ") ]
' testdata.ssv
#👇配列として表示
[
  [
    "山下モゲ雄",
    "営業部",
    "本社",
    "3年"
  ],
  [
    "島田フガ子",
    "経理部",
    "名古屋支部",
    "15年"
  ],
  [
    "岡田ピポ太",
    "製造部",
    "山口工場",
    "8年"
  ],
  [
    "沢口モフ代",
    "人事部",
    "本社",
    "4年"
  ],
  [
    "銭形ガメ吉",
    "海外部",
    "メキシコ支部",
    "11年"
  ]
]
        

Sedでテキスト全体を一括削除する方法

👇文字列中の特定記号を一括削除する

            
            ・Sedの正規表現の使い方を思い出したい
・テキストを高速に特定の文字を一括削除をしたい
        
            
            $ echo 'a b c d e f g' | sed -r 's/[[:space:]]//g'
abcdefg

$ echo 'HEX: 01 2e 24 a5 8c 2f de' | sed -r 's/[[:xdigit:]]//g'
HX:
        

Sedで文字列の中の空白文字を削除する

👇不要な空白(文字列前後の空白や連続した空白)の削除

            
            ・Sedで空白文字が上手く削除されない理由が知りたい
・Sedで空白文字を細かく制御したい
        
            
            $ sed -r '
s/"[[:blank:]]+/"/g
s/\\n[[:blank:]]+/\\n/g
s/[[:blank:]]+"/"/g
s/[[:blank:]]+\\n/\\n/g
s/[[:blank:]]+/ /g
' <<EOF
"      のどか  な\n       田園      風景    ","       あ       \n小林      さん!","  メガネ  は\n   ずれ   落ち        る"
EOF
"のどか な\n田園 風景","あ\n小林 さん!","メガネ は\nずれ 落ち る"
        

SedコマンドでCSVデータから列の区別なくキーを含んでる行を全抽出

👇特定の文字列を含む行を抽出する

            
            ・ CSVデータで不特定の列にキーワードが分布しているパターンを操作したい
        

            
            $ sed -n -r '
/貝|イカ/p
' <<EOF
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
EOF
#👇出力
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
        

Sedコマンドで複数行をまたぐ文字列パターンをマッチさせるための改行文字

👇改行も含めた正規表現パターンをキャプチャする方法

            
            ・Sedで改行文字を先読みさせて正規表現を使いたい
        

            
            $ str_show_2=${str_show//$'\n'/\\n}
$ echo $str_show_2 | sed -e 's/<head>.*<\/head>//g'
<!doctype html>\n<html lang="en">\n \n <body>\n <div>\n <header>\n <span>蛸壺のプロブラミング・ブログ</span>\n <a href="/home"><span>HOME</span></a>\n </header>\n <footer>\n <ul>\n <li><a href="/home">Home</a> |</li>\n <li><a href="/home#blog">Blog</a> |</li>\n <li><a href="/home#about">About</a> |</li>\n <li><a href="/home#contactus">Contact Us</a></li>\n </ul>\n </footer>\n </div>\n </body>\n</html>
        

SedとAwkでCSVデータの行と列を操作する基本

👇SedとAwkによるCsvファイルの行・列の操作アレコレ

            
            ・CSVデータ内の行と列をシェルコマンドでどう操作するか知りたい
        

            
            $ sed -i '$ a 出川 ゴボ之,営業,大阪支部,1年' employee.csv
$ cat employee.csv
山下 モゲ雄,営業部,本社,3年
島田 フガ子,経理部,名古屋支部,15年
岡田 ピポ太,製造部,山口工場,8年
沢口 モフ代,人事部,本社,4年
銭形 ガメ吉,海外部,メキシコ支部,11年
出川 ゴボ之,営業,大阪支部,1年

$ awk -F "," '
BEGIN {
    OFS=","
}
F == 0 {
    open_arr[$1] = $2;
    next;
}
{
    if($1 in open_arr) {
        print $1, open_arr[$1], $2, $3, $4;
    }
}
' F=0 add_employee.csv F=1 employee.csv > combined.csv
$ cat combined.csv
#👇出力
山下 モゲ雄,25歳,営業部,本社,3年
島田 フガ子,42歳,経理部,名古屋支部,15年
岡田 ピポ太,30歳,製造部,山口工場,8年
沢口 モフ代,27歳,人事部,本社,4年
銭形 ガメ吉,34歳,海外部,メキシコ支部,11年
        

巨大なCSVテキストをシェルコマンドで効率的に扱う

👇CSVデータから効率で高速に行&列の範囲を絞り込む

            
            ・巨大なCSVファイルから部分的に切り取ったデータを取り出したい
・Head/Tail/Cut/Trコマンドでより高速にテキストを捌く方法を知りたい
・Head/Tail/Cut/TrコマンドのCSVデータの使い方を知りたい
        

            
            #!/bin/bash

FILE_NAME=hoge.csv
TOTAL_LINES=$(wc -l hoge.csv | cut -d' ' -f1)
BUFFER_SIZE=3
START_READ=1
END_READ=$(($TOTAL_LINES / $BUFFER_SIZE))
LEFT_LINES=$(($TOTAL_LINES % $BUFFER_SIZE))
COLUMN_LIST=1,3
echo "TOTAL:${TOTAL_LINES} START:${START_READ} END:${END_READ} LEFT:${LEFT_LINES}"

do_something() {
    #DO SOMETHING...
    echo "$1"
}

for i in $(seq "$END_READ" -1 0); do
    while read LINE; do
        do_something $LINE
    done< <(
        if [ "$i" != 0 ] ; then
            head -n "$(( ($END_READ - $i + 1) * $BUFFER_SIZE ))" $FILE_NAME |
            tail -n "$(( $BUFFER_SIZE ))" |
            cut -f "$COLUMN_LIST" -d ","
        else
            tail -n "$(( $LEFT_LINES ))" $FILE_NAME |
            cut -f "$COLUMN_LIST" -d ","
        fi
    )
done
        

AwkとJqでCSVデータの空データをエラー値で埋める

👇検索対象が無いときの対処方〜エラーか#N/Aを返す

            
            ・Awkでセル内空白を空文字かヌルなのかを区別させたい
・Jqでセル内空白を空文字かヌルなのかを区別させたい
・Excel関数のようにエラー値を#N/Aで再現したい
        

            
            $ awk -F"," '{
    if ( typeof($1) != "strnum" || typeof($2) != "strnum" ) {
        print "#N/A";
    } else {
        print $1*$2;
    }
}' << EOF
3,6
4,19
8,3
5,22
4.5,9.13
526,0.0
9.1,0.0
EOF
#👇出力
#N/A
76
24
#N/A
41.085
0
#N/A
        

AwkでCSVデータの全てのセル要素を解析して重複を調べる

👇重複している要素を見つける&重複している要素のカウントする

            
            ・CSVデータの行・列区別なくセル要素の重複を調べたい
        

            
            $ echo "$RAW_DATASET" | awk -F"," '{
    for (i=1; i<=NF; i++) {
        if (!label[$i]++) {print $i;}
    }
}'
#👇出力
2
3
1
6
4
8
        

複数のCSVファイルを重複を考慮しながら合成する

👇複数のCSVファイルを重複を考慮しながら合成する

            
            ・バラバラになって複数存在してしまったCSVファイルを一つに統合したい
        

            
            $ awk -F "," 'BEGIN {OFS=","}
F == 0 {
    open_arr[$1] = $2;
    next;
}
F == 1 {
    if($1 in open_arr) {
        close_arr[$1] = $2;
    }
    next;
}
{
    if($1 in open_arr) {
        print $1, open_arr[$1], close_arr[$1], $2;
    }
}
' F=0 open.csv F=1 close.csv F=2 volume.csv
#👇実行結果
2020-05-19,1575,1567,9500
2020-05-20,1570,1598,9600
2020-05-21,1599,1551,8300
2020-05-22,1551,1541,3100
2020-05-25,1553,1578,3800
2020-05-26,1583,1569,9700
2020-05-27,1569,1569,14300
2020-05-28,1537,1570,18400
2020-05-29,1571,1558,12200
2020-06-01,1558,1554,4600
2020-06-02,1564,1588,11200
2020-06-03,1599,1569,12300
2020-06-04,1590,1565,8000
2020-06-05,1571,1566,8300
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

基本テクニック② 〜 表データから検索

ここからはちょっと進んだテクニックとして、「シェルコマンドでツール化させたスクリプトで検索してみる」をテーマにした記事を紹介していきます。

CSVデータの検索ツールの作り方の基礎

👇条件を与えて検索結果をCSVデータで出力

            
            ・CSVデータからデータを探すスクリプトの概要を知りたい
        

            
            #!/bin/bash

usage_exit() {
    echo "USAGE: $(basename $0) [-l key_list] [-h help] [input_file]" 1>&2
    exit 1
}

noarg_err() {
    echo "ERROR: must provide key_list!" 1>&2
    exit 1
}

noinputfile_err() {
    echo "ERROR: not allowed input file to be empty!" 1>&2
    exit 1
}

while getopts l: OPT; do
    case $OPT in
        l ) KEY_LIST="$OPTARG"
            ;;
        \? ) usage_exit
            ;;
    esac
done

shift $((OPTIND - 1))

if [ -z "$KEY_LIST" ]; then
    noarg_err
fi

if [ -z "$1" ]; then
    noinputfile_err
fi

echo "FILE: $1, KEY_LIST: ${KEY_LIST}"
        

検索用のインプットファイルを使ったCSVデータ検索のやり方

👇検索用CSVファイルから検索結果を出力

            
            ・データ検索を直接入力でなく、入力ファイルで操作したい
        

            
            #!/bin/bash

usage_exit() {
    echo "USAGE: $(basename $0) [-l key_list] [-h help] [input_file]" 1>&2
    exit 1
}

noarg_err() {
    echo "ERROR: must provide key_list!" 1>&2
    exit 1
}

selecteither_err() {
    echo "ERROR: should select an option from -l/-i!" 1>&2
    exit 1
}

noinputfile_err() {
    echo "ERROR: not allowed input file to be empty!" 1>&2
    exit 1
}

while getopts l:i: OPT; do
    case $OPT in
        l ) KEY_LIST="$OPTARG"
            ;;
        i ) KEY_LIST_FILE="$OPTARG"
            ;;
        \? ) usage_exit
            ;;
    esac
done

shift $((OPTIND - 1))

if [ -z "$KEY_LIST" ] && [ -z "$KEY_LIST_FILE" ]; then
    noarg_err
elif [ -n "$KEY_LIST" ] && [ -n "$KEY_LIST_FILE" ]; then
    selecteither_err
elif [ -z "$1" ]; then
    noinputfile_err
fi

echo "FILE: $1, KEY_LIST: ${KEY_LIST}, KEY_LIST(FILE): ${KEY_LIST_FILE}"

if [ -n "$KEY_LIST" ]; then
    PARR=($(echo "${KEY_LIST}" | tr ',' ' '))
    for p in "${PARR[@]}"; do
        awk -F"," '
            $1 ~ /'"$p"'/ { last_macthed = $0; }
            END { print last_macthed ? last_macthed : "'"$p"'?,#N/A,#N/A,#N/A"; }
        ' $1
    done
elif [ -n "$KEY_LIST_FILE" ] && [ -f "$KEY_LIST_FILE" ]; then
    cat "$KEY_LIST_FILE" | while read KEY || [ -n "${KEY}" ]; do
        awk -F"," '
            $1 ~ /'"$KEY"'/ { last_macthed = $0; }
            END { print last_macthed ? last_macthed : "'"$KEY"'?,#N/A,#N/A,#N/A"; }
        ' $1
    done
fi
        

自由度の高い検索ツールにするための機能拡張

👇複数条件で全列を対象に検索して表示する

            
            ・ CSVデータを複雑な条件で検索するツールを作りたい
        

            
            #!/bin/bash

usage_exit() {
    echo "USAGE: $(basename $0) [-l key_list] [-h help] [input_file]" 1>&2
    exit 1
}

noarg_err() {
    echo "ERROR: must provide key_list!" 1>&2
    exit 1
}

selecteither_err() {
    echo "ERROR: should select an option from -l/-i!" 1>&2
    exit 1
}

noinputfile_err() {
    echo "ERROR: not allowed input file to be empty!" 1>&2
    exit 1
}

while getopts l:i: OPT; do
    case $OPT in
        l ) KEY_LIST="$OPTARG"
            ;;
        i ) KEY_LIST_FILE="$OPTARG"
            ;;
        \? ) usage_exit
            ;;
    esac
done

shift $((OPTIND - 1))

if [ -z "$KEY_LIST" ] && [ -z "$KEY_LIST_FILE" ]; then
    noarg_err
elif [ -n "$KEY_LIST" ] && [ -n "$KEY_LIST_FILE" ]; then
    selecteither_err
elif [ -z "$1" ]; then
    noinputfile_err
fi

echo "FILE: $1, KEY_LIST: ${KEY_LIST}, KEY_LIST(FILE): ${KEY_LIST_FILE}"

if [ -n "$KEY_LIST" ]; then
    PARR=($(echo "${KEY_LIST}" | tr ',' ' '))
    for p in "${PARR[@]}"; do
        awk -F"," '
            $1 ~ /'"$p"'/ { last_macthed = $0; }
            END { print last_macthed ? last_macthed : "'"$p"'?,#N/A,#N/A,#N/A"; }
        ' $1
    done
elif [ -n "$KEY_LIST_FILE" ] && [ -f "$KEY_LIST_FILE" ]; then
    cat "$KEY_LIST_FILE" | while read KEY || [ -n "${KEY}" ]; do
        K=($(echo "${KEY}" | awk -F",{1}" '{k1=$1?$1:"NULL";k2=$2?$2:"NULL";k3=$3?$3:"NULL";k4=$4?$4:"NULL";print k1,k2,k3,k4;}'))
        echo "+++ MATCHING-KEYS 1: ${K[0]} 2: ${K[1]} 3: ${K[2]} 4: ${K[3]} +++ "
        awk -F"," '
            function isSkip(s_){return s_ == "NULL";}
            {
                ch1 = !isSkip("'"${K[0]}"'");
                ch2 = !isSkip("'"${K[1]}"'");
                ch3 = !isSkip("'"${K[2]}"'");
                ch4 = !isSkip("'"${K[3]}"'");
                total = ch1 + ch2 + ch3 + ch4;
                if (ch1 && $1 !~ /'"${K[0]}"'/) {ch1=0}
                if (ch2 && $2 !~ /'"${K[1]}"'/) {ch2=0}
                if (ch3 && $3 !~ /'"${K[2]}"'/) {ch3=0}
                if (ch4 && $4 !~ /'"${K[3]}"'/) {ch4=0}
                if (ch1 + ch2 + ch3 + ch4 == total) {print $0}
            }
        ' $1
    done
fi
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

基本テクニック③ 〜 CSVでデータ集計

ここからはもう少しテクニックを膨らまして「CSV(コンマ切り)形式でデータを集計できる自作ツールスクリプトを作る」をテーマにした記事の紹介です。

対話的に集計項目を選択できるスクリプトの作成の基本

👇集計を対話的にするスクリプト作成の基礎

            
            ・対話的に操作できるツールスクリプトが作成したい
        

            
            #!/bin/bash

function DoAScript() {
    echo "スクリプトA: $1が選択されました。"
}

function DoBScript() {
    echo "スクリプトB: $1が選択されました。"
}

function Addup() {
    printf "集計したい項目を 1 か 2 で選択してください\n"
    printf "\t1) 月間総来客数 \t2) 月間総売上\n"
    printf "※ 終了は q か c を入力!\n>>>"
    read OPT

    if [ $OPT == '1' ] ; then
        DoAScript "$OPT"
    elif [ $OPT == '2' ] ; then
        DoBScript "$OPT"
    elif [ $OPT == 'q' ] || [ $OPT == 'c' ] ; then
        echo "終了"
        exit 1
    else
        printf "ヒント...1 か 2 で入力!\n\n"
        Addup
    fi
}

Addup
        

正規表現を使った集計操作を行うスクリプトの作成

👇複雑な文字パターンの条件で集計する

            
            ・セル文字列の要素に曖昧さを含んだ CSVデータでも集計を行いたい
        

            
            #!/bin/bash

declare -A branches=(
    ['1']='営業部'
    ['2']='経理部'
    ['3']='製造部'
    ['4']='海外部'
)

function Total() {
    local option="${branches[$1]}"
    local filepath="$2"
    cat "$filepath" | awk -F"," '
        $2 ~ /'$option'/ { addup += $4 }
        END {print "\n  '$option' : " addup " 円"}
    '
}

function Addup() {
    local option
    printf "集計したい部署を以下 1/2/3/4 から選択してください\n"
    printf "\n  1) 営業部  2) 経理部  3) 製造部 4) 海外部\n\n"
    printf "※ 終了は q か c を入力!\n>>>"
    read OPT
    case "$OPT" in
        1 | 2 | 3 | 4 ) Total $OPT $1; option=$OPT;;
        q | c ) echo "終了"; exit 0;;
        * ) printf "ヒント... 1/2/3/4 で入力!\n\n"; Addup $1;;
    esac
    [ -n "$option" ] && exit 1
}

Addup $1
        

複数の集計条件で集計操作を行うスクリプトの作成

👇複数の条件が重なる場合に集計を行う

            
            ・CSVデータで複数の列で集計条件を同時に満たす要素だけで集計がしたい
        

            
            #!/bin/bash

declare -A branches=(
    ['1']='営業部'
    ['2']='経理部'
    ['3']='製造部'
    ['4']='海外部'
)

declare -A locations=(
    ['1']='本社'
    ['2']='名古屋'
    ['3']='山口'
    ['4']='ベトナム'
    ['5']='メキシコ'
)

function Total() {
    local b="${branches[$1]}"
    local l="${locations[$2]}"
    local filepath="$3"
    cat "$filepath" | awk -F"," '
        $2 ~ /'$b'/ && $3 ~ /'$l'/ { addup += $4 }
        END {print "\n  '$b' '$l' : " addup " 円"}
    '
}

function Addup() {
    local opt1 opt2

    printf "集計したい部署を以下 1/2/3/4 から選択してください\n"
    printf "\n  1) 営業部  2) 経理部  3) 製造部  4) 海外部\n\n"
    printf "※ 終了は q か c を入力!\n>>>"
    read OPT1
    case "$OPT1" in
        1 | 2 | 3 | 4 ) opt1=$OPT1;;
        q | c ) echo "終了"; exit 0;;
        * ) printf "ヒント... 1/2/3/4 で入力!\n\n"; Addup $1;;
    esac

    printf "集計したい勤務地を以下 1/2/3/4/5 から選択してください\n"
    printf "\n  1) 本社  2) 名古屋  3)  山口  4) ベトナム  5) メキシコ\n\n"
    printf "※ 終了は q か c を入力!\n>>>"
    read OPT2
    case "$OPT2" in
        1 | 2 | 3 | 4 | 5 ) Total $opt1 $OPT2 $1; opt2=$OPT2;;
        q | c ) echo "終了"; exit 0;;
        * ) printf "ヒント... 1/2/3/4/5 で入力!\n\n"; Addup $1;;
    esac
    [ -n "$opt1" ] || [ -n "$opt2" ] && exit 1
}

Addup $1
        

エクセル時間を持つ列に対して集計操作を行う

👇日付範囲で細かい条件指定した集計を行う

            
            ・日付時間を集計条件に指定したい
・Dateコマンドの出力フォーマットを良く知りたい
        

            
            #!/bin/bash

function TotalCustomerOrSales() {
    local option=$(( $1 + 1 ))
    local mode="$2"
    local filepath="$3"
    cat "$filepath" | awk -v mode=$mode -F"," '
        function excel_month(rawtime) {
            parsed_time = (rawtime - 1) * 60 * 60 * 24 - 2209075200;
            cmd="date -d @"parsed_time " +\"%m\"";
            cmd | getline month_; close(cmd);
            return month_;
        }
        function excel_week(rawtime) {
            parsed_time = (rawtime - 1) * 60 * 60 * 24 - 2209075200;
            cmd="date -d @"parsed_time " +\"%W\"";
            cmd | getline week_; close(cmd);
            return week_;
        }
        function excel_day(rawtime) {
            parsed_time = (rawtime - 1) * 60 * 60 * 24 - 2209075200;
            cmd="date -d @"parsed_time " +\"%u\"";
            cmd | getline day_; close(cmd);
            return day_;
        }
        BEGIN {
            # Array of months
            for (i=1;i<=12;i++) {
                m[i-1] = i > 9 ? i "" : "0" i;
            }
            # Array of weeks
            for (i=0;i<=53;i++) {
                w[i] = i > 9 ? i "" : "0" i;
            }
            # Array of days of the week
            for (i=1;i<=7;i++) {
                d[i-1] = i "";
            }
        }
        {
            if (mode == 1) {
                for (i in m) {
                    if ( excel_month($1) == m[i] ) {
                        if (mSummary[i] == "" ) {
                            mSummary[i] = $'$option'
                        } else {
                            mSummary[i] += $'$option'
                        }
                    }
                }
            } else if (mode == 2) {
                for (i in w) {
                    if ( excel_week($1) == w[i] ) {
                        if (wSummary[i] == "" ) {
                            wSummary[i] = $'$option'
                        } else {
                            wSummary[i] += $'$option'
                        }
                    }
                }
            } else if (mode == 3) {
                for (i in d) {
                    if ( excel_day($1) == d[i] ) {
                        if (dSummary[i] == "" ) {
                            dSummary[i] = $'$option'
                        } else {
                            dSummary[i] += $'$option'
                        }
                    }
                }
            }
        }
        END {
            if (mode == 1) {
                for (i in mSummary) {
                    print m[i] "月:" mSummary[i]
                }
            } else if (mode == 2) {
                for (i=0 ; i < length(w) ; i++ ) {
                    if (wSummary[i] != "") { print w[i] "週:" wSummary[i] }
                }
            } else if (mode == 3) {
                for (i in dSummary) {
                    print d[i] "曜日:" dSummary[i]
                }
            }
        }
    '
}
        

平均などの算術計算をともなう集計スクリプトの作成

👇平均値で集計計算する

            
            ・単純な計算だけでなく、数学的な操作をデータ解析したい
        
            
            #!/bin/bash

declare -A categories=(
    ['1']='営業部'
    ['2']='経理部'
    ['3']='製造部'
    ['4']='海外部'
    ['5']='本社'
    ['6']='名古屋'
    ['7']='山口'
    ['8']='ベトナム'
    ['9']='メキシコ'
)

function Average() {
    local option="${categories[$1]}"
    local filepath="$2"
    cat "$filepath" | awk -F"," '
        BEGIN { count = 0 }
        $2 ~ /'$option'/ || $3 ~ /'$option'/ {
            avrg[count++] = $4;
        }
        END {
            result = 0;
            for (i = 0; i < count; i++ ) { result += avrg[i] }
            result = count > 0 ? result / count : 0;
            print "\n  '$option' (" count "人)の平均値 : " result " 円";
        }
    '
}

function Addup() {
    local option
    printf "集計したい部署を以下 1/2/3/4 から選択してください\n"
    printf "\n  1) 営業部  2) 経理部  3) 製造部  4) 海外部"
    printf "\n  5) 本社    6) 名古屋  7) 山口    8) ベトナム  9) メキシコ\n\n"
    printf '※ 終了は q  か c を入力!\n>>>'
    read OPT
    case "$OPT" in
        [1-9]* ) Average $OPT $1; option=$OPT;;
        q | c ) echo "終了"; exit 0;;
        * ) printf "ヒント... 1から9 で入力!\n\n"; Addup $1;;
    esac
    [ -n "$option" ] && exit 1
}

Addup $1
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

基本テクニック④ 〜 シェルスクリプトとExcelとの連携

ここからは「シェルスクリプトからExcelファイルをどう扱うか」をテーマにした記事をまとめて紹介します。

xlsx2csvを使ってExcelファイルの直接操作

👇LinuxでExcelファイル(xls/xlsx)をCSVデータに変換するには?

            
            ・OS環境に依らずLinuxでもExcelファイルを直接読み込みたい
・OS環境に依らずLinuxでもExcelファイルからCSVデータを保存したい
        

            
            $ xlsx2csv -s 1 book1.xlsx | awk -F"," '
    { print $1, $2, $3; }
'
#👇出力
1 2 3
4 5 6

$ xlsx2csv -s 2 book1.xlsx | awk -F"," '
    { print $1, $2, $3; }
'
#👇出力
7 8 9
a b c
        

xlsx2csvでExcelファイルからCSVデータと取り出したときのセル内改行

👇Excelデータシートのセル内改行をCsvファイルで取り扱う方法

            
            ・CSVデータのセル内改行の扱い方を知りたい
        

            
            $ xlsx2csv -e hoge.xlsx | awk -F"," '{ print $1, $2, $3; }'
#👇出力
のどかな\n田園風景 あ\n小林さん! メガネは\nずれ落ちる
w e l
12 5 7
        

Linuxコマンドのみでcsvデータからxlsxファイルへ変換する方法

👇Linuxでシェルコマンドからエクセルファイル(XSLX)を新規作成する方法〜「libreoffice」と「ssconvert」

            
            ・Linux環境だけでもxlsxファイルを作りたい
・Excelなしでxlsxファイルにデータを作成・管理したい
        

            
            $ ssconvert example.csv example.xlsx

$ xlsx2csv example.xlsx
名前,性別,年齢,住所
ピヨ田 モブ雄,男,35,地球
ベモ山 デン実,女,43,火星
        


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

Jqコマンドを利用したCSV操作

ここからは前節までは紹介しきれていなかった「Jqコマンドを使ったCSVファイルの編集テクニック」の特集記事を取り上げていきます。

JqとXargsを使ったシェルスクリプトのパイプ処理化をコツ

👇【Jqコマンド応用編】xargsをwhile/forループの代わりとして使う場合の勘所

            
            ・Jqを使ったスクリプトとても重い
        

            
            #!/bin/bash

employee=$(cat << EOF
[
    {"社員":"山下モゲ雄","部署":"営業部","事業所":"本社","勤続":"3年"},
    #中略...上記で説明したデータセット
    {"社員":"山下モゲ雄","部署":"営業部","事業所":"埼玉支部","勤続":"3年"},
]
EOF
)

employee=$(
echo "$employee" | jq -c '.[]' | sed -e 's/"/\\"/g' | xargs -n1 bash -c '
    echo "$0" | jq -c "(.[\"部署\"] |= \"営業部\") | (.[\"事業所\"] |= \"埼玉支店\")"
')

echo "["${employee//$'\n'/,}"]" | jq -c '.'
        

JqコマンドでJSONデータを扱う際に利用するコマンドオプション

👇【Jqコマンド実用編】押さえておきたいデータ入出力のためのJqのコマンドオプションまとめ

            
            ・Jqの入力データの取り込みが思うように上手くいかない
・Jqの出力データのフォーマットが思うような形になっていない
        

            
            $ jq --slurp '.' << EOF
[
    {"name": "バミ田 ポプ雄","age": 43,"branch": "本社"},
    {"name": "ギャマ川 ノリュ実","age": 23,"branch": "福岡支店"},
    {"name": "ドル間 ハム吉","age": 33,"branch": "広島支店"},
]
EOF
#👇出力
[
  [
    {
      "name": "バミ田 ポプ雄",
      "age": 43,
      "branch": "本社"
    },
    {
      "name": "ギャマ川 ノリュ実",
      "age": 23,
      "branch": "福岡支店"
    },
    {
      "name": "ドル間 ハム吉",
      "age": 33,
      "branch": "広島支店"
    }
  ]
]
        

JSONデータとCSVデータを相互に変換

👇Jq&AwkコマンドでJSONファイル⇔CSVファイルに相互変換する方法を考察

            
            ・Jq&AwkコマンドでCSVデータをJSONデータに変換したい
・Jq&AwkコマンドでJSONデータをCSVデータに変換したい
        

            
            $ CSV_TEXT=$(cat << EOF
hoge,piyo,fuga,moga,buyo
120,こんにちは,3.14,ごきげんだぜ,false
54,コンバンワ,-8.07,,true
-89,てやんでぇ,1.2E-3,さいあくだ,
EOF
)

$ echo "$CSV_TEXT" | awk -F"," '
    NR == 1 {
        rowCount = 0;
        for (i = 1; i <= NF; i++) {key[i] = $i;}
    }
    NR > 1 {
        rowCount++;
        for (i = 1; i <= NF; i++) {
            if ($i != "") {
                if ($i ~ /^[+-]?([0-9]+[.]?[0-9]*|[.][0-9]+)([eE][+-]?[0-9]+)?$/) {
                    value[rowCount][i] = "{\"key\":\"" key[i] "\",\"value\":" $i "}";
                }
                else if (tolower($i) ~ /(true|false|null)/) {
                    value[rowCount][i] = "{\"key\":\"" key[i] "\",\"value\":" $i "}";
                }
                else {
                    value[rowCount][i] = "{\"key\":\"" key[i] "\",\"value\":\"" $i "\"}";
                }
            }
        }
    }
    END {
        for (j=1;j<=rowCount;j++) {
            rslt = "[";
            for (i = 1; i <= NF; i++) {
                if (value[j][i] == null) { continue; }
                else if (i == NF) { rslt = rslt value[j][i]; }
                else { rslt = rslt value[j][i] ","; }
            }
            sub(/,$/, "", rslt);
            print rslt "]";
        }
    }
' | jq 'from_entries' | jq -s '.'
#👇出力結果
[
  {
    "hoge": 120,
    "piyo": "こんにちは",
    "fuga": 3.14,
    "moga": "ごきげんだぜ",
    "buyo": false
  },
  {
    "hoge": 54,
    "piyo": "コンバンワ",
    "fuga": -8.07,
    "buyo": true
  },
  {
    "hoge": -89,
    "piyo": "てやんでぇ",
    "fuga": 0.0012,
    "moga": "さいあくだ"
  }
]
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

Awkコマンドを使った便利なテクニック関連

ここからは上までの内容で取り上げいない「Awkコマンドの有用なテクニック」を紹介しているページです。

Jqがインストールできない人のためのAwkでJsonファイルを扱うテクニック

👇AWKを使ってテキストからjsonを生成する

            
            ・Jqを使いたいのに、インストール必須なpythonが諸事情等で使えない
        

            
            $ cat input.dat | awk '
    BEGIN{
        s_pos = 0;
        conv_json = "[";
    }
    /[0-9]{4}-[0-9]{2}-[0-9]{2}/{
        s_pos = NR;
        if(NR == s_pos) {
            date = "\"date\":\"" $0 "\""
        }
    }
    /^[0-9\.]+$/{
        if(NR == s_pos+1) {
            open = "\"open\":" $0
        }
        if(NR == s_pos+2) {
            high = "\"high\":" $0
        }
        if(NR == s_pos+3) {
            low = "\"low\":" $0
        }
        if(NR == s_pos+4) {
            closed = "\"close\":" $0
        }
        if(NR == s_pos+5) {
            volume = "\"volume\":" $0
        }
    }
    NF == 0{
        if(NR == s_pos+6) {
            content = "{" date "," open "," high "," low "," closed "," volume "}";
            conv_json = conv_json content ","
        }
    }
    END{
        sub(/,$/, "", conv_json);
        conv_json = conv_json "]";
        print conv_json
    }
'
        

AwkのカスタムソートでCSVデータの複雑な複雑な並び替え

👇gawkでカスタムソート

            
            ・CSVデータを独自のルールで並び替えたい
        

            
            $ EXAM_SCORE=$(cat << EOF
Ichiro 84
Bob 25
Wakame 76
Hanako 56
Alice 90
Kabao 53
Jam 43
Tarao 25
Cheese 12
Kasuo 47
Piyoko 88
Ikura 29
EOF
)

$ echo "$EXAM_SCORE" | awk '
function cmp_num_val(i1, v1, i2, v2) {
    if (v1 < v2) {
        return -1;
    } else {
        return 1;
    }
}
{
    data[$1] = $2;
}
END {
    PROCINFO["sorted_in"] = "cmp_num_val";
    for (j in data) {
        printf("data[%s] = %s\n", j, data[j]);
    }
}
'
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

その他〜覚えておくとお得なテクニック

CSV・Excelのシェルスクリプトからの操作とは直接的には少し話題が逸れますが、覚えておいたほうが良い/場合によっては必要になってくると思われるページです。

Excel特有の時間形式・『エクセル時間』をDateコマンドで自在に変換

👇Excelでの時間の計算をどう取り扱うのか 〜 DATEコマンドの計算方法

            
            ・シェルコマンドでエクセル時間から通常の時間表記にしたい
・シェルコマンドで通常の時間表記からエクセル時間にしたい
        

            
            $ echo '2021年01月01日'|
    sed -r 's/([0-9]{4})[^0-9]+([0-9]{1,2})[^0-9]+([0-9]{1,2})[^0-9]+/\1-\2-\3/g'|
    awk -F"," '
    function parse_epochtime(rawtime) {
        cmd="date -u --date=\""rawtime" 00:00:00\" +\"%s\"";
        cmd | getline parsed_time
        close(cmd)
        parsed_time = (parsed_time + 2209075200)/60/60/24 + 1;
        return parsed_time;
    }
    {
        epochtime = parse_epochtime($1);
        print epochtime
    }
'
44197
        

DateコマンドでExcelファイルからCSVデータを抽出する際の時間形式を変換

👇日付を含むエクセルデータをエクスポートしたときのCSVデータを取り扱う

            
            ・エクセル時間をシェルスクリプト内でちゃんとした時間で表示したい
        

            
            $ cat accounting.csv | awk -F"," '
    function parse_excel_date(rawtime) {
        parsed_time = (rawtime - 1) * 60 * 60 * 24 - 2209075200;
        excel_date = strftime("%Y年%m月%d日", parsed_time);
        return excel_date;
    }
    BEGIN{ OFS="," }
    {
        print parse_excel_date($1),$2,$3;
    }
'
#👇出力
2021年01月01日,51,98875
2021年01月02日,91,150457
2021年01月03日,77,134982
        

引数を渡せるシェルスクリプトの作成方法

👇引数指定できるシェルスクリプトを自作方法

            
            ・自作スクリプトで単純な引数の引き渡しの方法が知りたい
・getoptsを使った自作スクリプトの作り方が知りたい
・引数解析付きの自作スクリプトの作り方が知りたい
        

            
            #!/bin/bash
PROGNAME="$(basename $0)"

usage() {
cat << EOS >&2
Usage: ${PROGNAME} [--hoge] [-1, --fuga [VALUE]] [-2, --piyo VALUE]
    A sample script of parsing on bash.
Options:
    --hoge        A single option.
    --fuga        A option with optional value.
    --piyo        A option with required value.
    -h, --help    Show usage.
EOS
    exit 1
}

PARAM=()

for opt in "$@"; do
    case "${opt}" in
        '-h' | '--help' )
            usage
            ;;
        '--hoge' )
            HOGE=true; shift
            ;;
        '-1' | '--fuga' )
            FUGA=true; shift
            if [[ -n "$1" ]] && [[ ! "$1" =~ ^-+ ]]; then
                FUGA_VALUE="$1"; shift
            fi
            ;;
        '-2' | '--piyo' )
            if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]; then
                echo "${PROGNAME}: Option needs an argument -- $( echo $1 | sed 's/^-*//' )" 1>&2
                exit 1
            fi
            PIYO=true; PIYO_VALUE="$2"; shift 2
            ;;
        '--' | '-' )
            shift
            PARAM+=( "$@" )
            break
            ;;
        -* )
            echo "${PROGNAME}: Invalid option detected -- '$( echo $1 | sed 's/^-*//' )'" 1>&2
            exit 1
            ;;
        * )
            if [[ -n "$1" ]] && [[ ! "$1" =~ ^-+ ]]; then
                PARAM+=( "$1" ); shift
            fi
            ;;
    esac
done

INPUT_FILE="${PARAM}"; PARAM=("${PARAM[@]:1}")
[[ -z "${INPUT_FILE}" ]] && usage

if [[ -n "${PARAM[@]}" ]]; then
    usage
fi

cat << EOS
HOGE > ${HOGE:-false} : FUGA > ${FUGA:-false} : PIYO > ${PIYO:-false}
FUGA_VALUE > ${FUGA_VALUE} : PIYO_VALUE > ${PIYO_VALUE}
INPUT_FILE < ${INPUT_FILE}
EOS
        

WindowsでもLinuxのシェルコマンドを使えるようにするbusyboxの紹介

👇Windowsでも使えるシェルコマンドツール・busybox

            
            ・Windowsで簡単にシェルコマンドを実行させたい
        

busyboxのDateコマンドを使うときの注意点

👇BusyboxのDateコマンドを使う

            
            ・Gnu dateコマンドの基礎を知りたい
・Awkスクリプトの中でもdateコマンドを使いたい
        

            
            $ date -d "2018-03-13" "+%Y年%m月%d日"
2018年03月13日
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

記事リンク・ダイジェスト

このブログ内で、シェルスクリプトで「Excel/CSVを扱って業務に活かそう」をテーマに扱っているページを一覧にしてまとめます。

人気記事!
合同会社タコスキングダム|蛸壺の技術ブログ

【xlsx2csvコマンド活用編】Linux環境でExcelファイル(xls/xlsx)をCSVデータに変換する

2021/04/02
ID#:122
シェルスクリプト xlsx2csv Excel業務支援

【xlsx2csvコマンド活用編】Linux環境でExcelファイル(xls/xlsx)をCSVデータに変換する

今回はExcelでCsv形式のデータをエクスポートしたいけど、WindowsOSのパソコンは無し、Linuxしか使いたくない方のためのxlsx2csvコマンドの紹介記事です。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

Linuxでシェルコマンドからエクセルファイル(XSLX)を新規作成する方法〜「libreoffice」と「ssconvert」

2023/06/30
ID#:206
シェルスクリプト Excel業務支援

Linuxでシェルコマンドからエクセルファイル(XSLX)を新規作成する方法〜「libreoffice」と「ssconvert」

LinuxユーザーのためのExcelファイル(XLSX形式)をより快適扱うためのワンポイント講座です。今回はCSVファイルから直接XLSXファイルに変換が可能な「libreoffice」と「ssconvert」コマンドを紹介します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

Excelでの時間の計算をシェルスクリプトでどう取り扱うのか〜DATEの計算方法

2021/04/13
ID#:120
シェルスクリプト Date Excel業務支援

Excelでの時間の計算をシェルスクリプトでどう取り扱うのか〜DATEの計算方法

エクセルでの日付時間とシェルスクリプトの扱うUNIX時間とは一見取り扱っているデータの表示が同じようで、日付の換算方法は異なります。ここではExcel時間表示フォーマットの話と、それをシェルスクリプトでどう補正するとCSVインポート・エクスポートが上手くいくのかを考察してみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】CSVデータから日付範囲で細かい条件指定した集計を行う

2021/04/16
ID#:115
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】CSVデータから日付範囲で細かい条件指定した集計を行う

CSVデータの集計操作系のスクリプトツールを作成してみる特集の第1回目です。今回はCSVデータの集計操作の基礎的な内容も掘り下げつつ、後半で少し応用的なツールスクリプトに仕上げる方法をじっくり解説していきます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

日付を含むエクセルデータをエクスポートしたときのCSVデータの時間表示をシェルスクリプトで取り扱う方法

2021/04/14
ID#:114
シェルスクリプト 日付データ Excel業務支援

日付を含むエクセルデータをエクスポートしたときのCSVデータの時間表示をシェルスクリプトで取り扱う方法

ExcelデータからCsv形式へインポート/エクスポートする際に気をつけておかなかればならない一つの日付を取り扱う換算ルールを特集します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】平均値の算出 〜 Awkを使った平均を計算するスクリプト

2021/04/19
ID#:113
シェルスクリプト 集計操作 Excel業務支援

【シェルスクリプト&Excel】平均値の算出 〜 Awkを使った平均を計算するスクリプト

CSVデータの自由でより高機能な集計操作を行うスクリプトツールを作成してみる特集の第3回目です。Awkでも科学計算ほどの精度は無いものの、それでもかなり高度な算術計算処理をスクリプト内で実現することができます。今回は簡単な好例として平均を計算させてみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】複数条件を満たすときのみに集計するスクリプト

2021/04/18
ID#:112
シェルスクリプト Excel業務支援 集計

【シェルスクリプト&Excel】複数条件を満たすときのみに集計するスクリプト

CSVデータの自由でより高機能な集計操作を行うスクリプトツールを作成してみる特集の第3回目です。前回はCSVデータで特定の一列から条件を満たすものを正規表現で抽出・集計する方法を紹介しました。今回は検索が複数列に渡る条件を与えた集計スクリプトの作り方を考察します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】より複雑な条件を満たすのときのみに集計するスクリプト

2021/04/17
ID#:111
シェルスクリプト Excel業務支援 集計

【シェルスクリプト&Excel】より複雑な条件を満たすのときのみに集計するスクリプト

CSVデータの自由でより高機能な集計操作を行うスクリプトツールを作成してみる特集の第2回目です。今回は正規表現を用いてより自由度の高い集計スクリプトの作り方を簡潔に考えてみましょう。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】集計を対話的にするスクリプト作成の基礎

2021/04/15
ID#:110
シェルスクリプト Excel業務支援 対話型入力

【シェルスクリプト&Excel】集計を対話的にするスクリプト作成の基礎

Excelでの定番の業務テクニックとして要素検索と並んで良く利用されているのが集計操作です。基礎固めとしてまずは集計モードを対話に選択できるようなツールスクリプトに仕立てる前段階のユーザーインタラクティブなシェルスクリプトの実装方法を考えてみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】CSVデータの複数列から複数条件で検索して行データを表示させるスクリプト

2021/04/12
ID#:107
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】CSVデータの複数列から複数条件で検索して行データを表示させるスクリプト

CSVデータの検索に特化したエクセルでいうところのVLOOKUP関数のような機能をもつスクリプトツールを作成してみる特集の第3回目です。前の回に引き続いて、もっと自由に検索列を決められて、なおかつ複数の検索条件も与えられるように再度Awkをベースに拡張してみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】CSV形式で与えてある検索条件ファイルから検索結果を出力するスクリプト

2021/04/11
ID#:106
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】CSV形式で与えてある検索条件ファイルから検索結果を出力するスクリプト

CSVデータからエクセル操作機能を代替するスクリプトツールを作成してみる特集の第2回目です。今回はAwkコマンドでCVSファイル内からキーワードリスト検索&抽出するスクリプトツールを作成してみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】条件を与えて検索結果をCSVデータで出力するスクリプト

2022/08/07
ID#:105
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】条件を与えて検索結果をCSVデータで出力するスクリプト

CSVデータの検索に特化したエクセルでいうところのVLOOKUP関数のような機能をもつスクリプトツールを作成してみる特集の第1回目です。今回は読み込んだCSVデータの特定の1列を検索キーとして、指定した検索キーリストからヒットした要素を順にピックアップしてCSV形式で表示するスクリプトを作成してみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】Head/Tail/Cut/Trコマンドを使ってCSVデータから効率で高速に行&列の範囲を絞り出す方法

2021/04/09
ID#:103
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】Head/Tail/Cut/Trコマンドを使ってCSVデータから効率で高速に行&列の範囲を絞り出す方法

容量の大きなCSVデータ等を、高速かつ効率的にパイプライン処理するために、Head、Tail、Cutとその他のLinuxコマンドを使ったテクニックを紹介します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】検索対象が無いときの対処方法〜エラー時の値を#N/Aに置き換える

2021/04/07
ID#:98
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】検索対象が無いときの対処方法〜エラー時の値を#N/Aに置き換える

検索結果が無い行を発見したときに、通常は何も表示されないで無視されることが多いですが、エラーハンドリングを定義し、エラーを発見したときの処置も実装したい場合があります。たとえば、検索結果で一致しない行には、新しい内容を新規作成してそこに挿入する...などです。今回はCSVデータ使う上でのAwkとjqを使ったシェルスクリプトのエラーの捌き方の基礎を行っていきます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】SedコマンドでCsvデータから特定の文字列を含む行を抽出する

2021/04/06
ID#:97
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】SedコマンドでCsvデータから特定の文字列を含む行を抽出する

CSV形式のデータの中の、不特定で複数の行(もしくは複数のセル)に対象の文字列を含むような曖昧さのある場合には、Awkかjqで処理するには少し冗長な操作になるときがあります。今回は先にSedで特定の文字列を含む行をフィルタリングのやり方を、Awkかjqで利用する前の下処理の方法として紹介します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】Sedコマンドで不要な空白(文字列前後の空白や連続した空白)を削除

2021/04/05
ID#:96
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】Sedコマンドで不要な空白(文字列前後の空白や連続した空白)を削除

セルに含まれる文字列には、インデントとして無駄に連続した空白が詰まっていたり、タブやスペースなどの複数のタイプの空白が混合して入っていたりする場合が有ります。今回はSedを使った余計な空白文字の除去・洗浄に関した内容を解説します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【xlsx2csvを使おう!】 Excelデータシートのセル内改行をCsvファイルで取り扱う方法

2021/04/03
ID#:95
シェルスクリプト Xlsx2csv Excel業務支援

【xlsx2csvを使おう!】 Excelデータシートのセル内改行をCsvファイルで取り扱う方法

csvをシェルスクリプトで取り扱う上でもっとも厄介なものが改行文字です。今回は、Excelデータ中に現れるセル内改行を、xlsx2csvコマンドからCsv形式のテキストファイルで扱う方法を解説します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】文字列中の特定の記号を一括削除する方法

2021/04/07
ID#:94
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】文字列中の特定の記号を一括削除する方法

Csvデータ全体に渡って、セル内に含まれる文字列に区別無く存在する不要な記号を一括して削除したい場合が有ります。このような特殊記号は当然ながら手動で検索しながら一つ一つ消していくのも面倒です。今回はCsvファイルの全体に渡るような文字列の置き換えをSedコマンドを利用して、一気に、そして高速に不要な文字を削除する方法を紹介します。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】文字列の分割を分割を極める ~ split関数の使い方

2021/04/01
ID#:93
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】文字列の分割を分割を極める ~ split関数の使い方

CSV形式と似ているけどちょっと違う、コンマ以外の様々な区切り文字(セパレーター)をもったデータファイルから、柔軟・簡単に分割(split)する方法を解説していきます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】文字列の後方参照を理解する

2021/03/31
ID#:92
シェルスクリプト Excel業務支援

【シェルスクリプト&Excel】文字列の後方参照を理解する

csvデータのセル文字列の後方参照をAwkとjqの2つのパターンでどう実現するのかを考えてみるちょっとした技術記事です。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】CSVデータ編集で使える最低限覚えておきたい正規表現の活用法

2021/03/26
ID#:91
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】CSVデータ編集で使える最低限覚えておきたい正規表現の活用法

AwkやSedといったテキストを編集する代表的なコマンドをより高度に操作するためには、正規表現(Regular Expression)の理解が欠かせなくなります。マニアックな正規表現のテクニックなどは避けながら、一般的なAwk(GNU Awk)とjqでcsvファイルを操作する際に最低限覚えておきたい正規表現をまとめてみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】SedとAwkによるCsvファイルの行・列の操作アレコレ

2021/03/30
ID#:90
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】SedとAwkによるCsvファイルの行・列の操作アレコレ

CsvファイルをSedやAwkなどのLinuxコマンドからCsvデータの行と列の操作するための基礎的なテクニックをまとめてみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】シェルスクリプトで複数の条件による検索し結果をCSVで返す

2021/03/24
ID#:89
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】シェルスクリプトで複数の条件による検索し結果をCSVで返す

シェルスクリプトで、Awkかjqコマンドを使ってCSVフォーマットのファイルを色々と処理してみたい方に向けたお役立ちテクニック特集です。この回ではターゲットとなる列の要素に複数の条件を検索して、その検索結果をcsv形式で返すようなシェルスクリプトを作成してみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプト&Excel】CSVファイルで読み出した文字列を複雑なルールで置換したい

2021/03/19
ID#:88
シェルスクリプト Excel業務支援 CSV

【シェルスクリプト&Excel】CSVファイルで読み出した文字列を複雑なルールで置換したい

シェルスクリプトで、Awkかjqコマンドを使ってCSVフォーマットのファイルを色々と処理してみたい方に向けたお役立ちテクニック特集です。今回はシェルスクリプトでCSV形式の中の文字列置換を行う方法に関して考えてみます。

クリックするとリンク先へ飛びます
関連記事
合同会社タコスキングダム|蛸壺の技術ブログ

【シェルスクリプトをオフィス業務の主役に!】シェルスクリプトでエクセル作業を効率化する超活用術まとめ

2024/01/06
ID#:87
シェルスクリプト Excel業務支援

【シェルスクリプトをオフィス業務の主役に!】シェルスクリプトでエクセル作業を効率化する超活用術まとめ

シェルスクリプトはどこでもどんなOSでも基本的に使えて、一度使い方を覚えるとパソコン上でありとあらゆる操作を可能としてくれます。そこでオフィスで日々エクセル業務と向き合う多忙なオフィスワーカー向けに、シェルスクリプトの力で劇的に生産効率を改善しする方法を提案します。

クリックするとリンク先へ飛びます


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

まとめ

ここではこのサイトで取り扱ってきたCSVデータを実業務に活かすために必要なシェルスクリプトの編集テクニックを学んでいく上で、様々なテクニックを紹介してきた記事のまとめになります。

今後も不定期ですが記事を修正・増量していく予定です。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集