ひゃまだのblog

ひゃまだ(id:hymd3a)の趣味のブログ

Bashでカンマ区切りのCSVファイルを扱う

(2024-04-26 初稿)

こちらのblogは、ちょっと久しぶりにアップする。

最近、株の乱高下が激しいので、楽天証券保有株一覧を見ているのだけど、不要な列があったり、ちょっと特殊な集計をしたかったりするので、自分で表計算ソフトにちまちまとコピぺしていたんだけど、いい加減アホらしくなったので、python等で書けばちゃんと表計算ソフトのファイルを作成することができるが、テキストファイルが好きなのでBashの勉強のためにスクリプトを作ってみた。

ありがたいことに、楽天証券からは保有株一覧のファイルをダウンロードできるので、カンマ区切りのCSVファイルをダウンロードして利用することにした。

楽天証券CSVだけならば、変な文字列も無いのですぐにできたのだが、もう少し汎用的なCSVファイルでも、動作するようにしてみた。

まずは、カンマ区切りのCSVだからとIFSのデリミタをカンマ(,)してset関数で分割を考えたが、数字の1000単位のカンマがあり、あえなく撃沈。試行錯誤の結果、結局はダブルクォートを目印(デリミタ)にして、データを区切ることにした。

入力行から複数の値を取得するのは、read関数を使うと便利。

簡単なサンプルスクリプト

#!/usr/bin/env bash
# csv-split
# csvファイルの値を配列に
# 2024-04-25 ver0.01 start

test_line='"あ,い! う","a! b,c","123,456,789", "4,321"'

IFS='"' read  v1 v2 v3 v4 v5 v6 v7 v8 <<< "$test_line"
echo 'v1=' \""$v1"\"         #⇒ v1= ""
echo 'v2=' \""$v2"\"         # ⇒ v2= "あ,い! う"
echo 'v3=' \""$v3"\"         # ⇒ v3= ","
echo 'v4=' \""$v4"\"         # ⇒ v4= "a! b,c"
echo 'v6=' \""$v6"\"         # ⇒ v6=  "123,456,789"
echo 'v8=' \""$v8"\"         # ⇒ v8=  "4,321"
echo 'need_value=' \""$v4"\",\""$v8"\"  # ⇒ need_value= "a! b,c","4,321"

ダブルクォートをデリミタにしたことにより、最初の変数(v1)に空白、次(v2)に値、その次(v3)がカンマ、と偶数番目の変数に値が読み込まれる。

また、任意の値を選択して取得することも可能。

固定化したCSVファイルなら良いが、もう少し汎用性をもたせて読み込む値(変数)の数が変わる場合は、以下のとおりreadに-aオプションを付けて配列として読み込む方が都合が良い。

IFS='"' read -a csv_ary <<< "$test_line"
echo 'csv_ary[0]=' \""${csv_ary[0]}"\"  # ⇒ csv_ary[0]= ""
echo 'csv_ary[1]=' \""${csv_ary[1]}"\"  # ⇒ csv_ary[1]= "あ,い! う"
echo 'csv_ary[2]=' \""${csv_ary[2]}"\"  # ⇒ csv_ary[2]= ","
echo 'csv_ary[3]=' \""${csv_ary[3]}"\"  # ⇒ csv_ary[3]= "a! b,c"
(以下、省略)

配列の添字が、0から始まっているので、今度は奇数番目に値が入っている。

1番目⇒1、2番目⇒3、3番目⇒5の添字を指定するが、n番目のデータは2n-1の添字を使えば値を取得できる。

また、値の順番を変更できるようにorderを指定できるようにし、かつ、関数にしたものが以下のとおり。

#!/usr/bin/env bash
# csv-split
# csvファイルを配列に分割する
# 2024-04-25 ver0.01 start
test_line='"あ,い! う","a! b,c","123,456,789", "4,321"'

get_csv_value() {
  # csvの値を指定する順番で出力
  local rslt=""
  IFS='"' read -a csv_ary <<< "$1"
  #echo 'csv_ary=' "${csv_ary[@]}"
  IFS=, read -a order_ary <<< $2
  #echo 'order_ary=' "${order_ary[@]}"
  for ((i=0; i<${#order_ary[@]}; i++)); do
    j=$((${order_ary[$i]} * 2 -1))      # n番目は配列の2n-1番目
    rslt+=\""${csv_ary[$j]}"\",
  done
  echo ${rslt%,}     # 最後の,の削除

order="2,1,3"         # 順番の指定
putline=$(get_csv_value "$test_line" "$order")
echo $putline

実行権を与えてから、実行すると以下のとおり。

# csv-split
"a! b,c","あ,い! う","123,456,789"

今回、read関数で配列にすることが便利なことがわかった。

どなたかの参考になれば幸い。

関連ページ

Debian 12(Bookworm)で、Bluetooth USBアダプタ(UB500)を接続してワイヤレスヘッドホンをつなぐ

(2024-04-03 初稿)

過去に何度もBluetooth接続で、スピーカーやマウスをつないだけど、接続方法をすぐに忘れてしまうのでメモを残す。

今回は、デスクトップのDebianに有線接続でヘッドホンをつないでいたんだけど、少しケーブルが短かったため、ヘッドホンを付けたまま自由な姿勢がとれるようにBluetooth接続のワイヤレスヘッドホンをつなぐことを目的とした。

まずは、筆者の環境を確認。

$ cat /etc/debian_version 
12.5
$ uname -a
Linux hoge 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 GNU/Linux

今回は、以下のサイトを参考にさせていただいた。多謝。m(__)m

デスクトップPCにはBluetoothアダプタが付いていなかったので、以下のUB500というBluetooth USBアダプタを購入した。

上記USB500をデスクトップPCに挿し込んでから、lsusbで確認。

$ lsusb
(前略)
Bus 001 Device 003: ID 2357:0604 TP-Link TP-Link UB500 Adapter
(後略)

ちゃんと認識しているよう。

今回接続するのは、骨伝導のワイヤレスヘッドホンでというもの。

以下のリンクよりも古い型なので、少し形状が異なるけど…

参考にしたサイトにあるとおり、Bluetooth関連のパッケージをインストールして、起動時から使えるように。

$ sudo apt update
$ sudo apt install bluetooth bluez bluez-tools rfkill
$ sudo systemctl start bluetooth
$ sudo systemctl enable bluetooth

以下のコマンドで、Bluetoothのstatusを確認。

$ sudo systemctl status bluetoothbluetooth.service - Bluetooth service<
     Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; preset: en>
     Active: active (running) since Sat 2024-03-30 15:10:32 JST; 1min 14s ago
       Docs: man:bluetoothd(8)
   Main PID: 685 (bluetoothd)
     Status: "Running"
      Tasks: 1 (limit: 19037)
     Memory: 3.3M
        CPU: 28ms
     CGroup: /system.slice/bluetooth.service
             └─685 /usr/libexec/bluetooth/bluetoothdr

rfkillのリストに入っていないことを確認。

$ rfkill list

bluetoothctlコマンドで、scanしてペアリングする。

$ bluetoothctl
[bluetooth]# scan on [NEW] Device EB:06:EF:66:A9:E1 X 11

X11のヘッドホンが見つかれば、スキャンは成功。

つづけて、bluetoothctlコマンドの中で、ペアリング。

# pair EB:06:EF:66:A9:E1
Attempting to pair with EB:06:EF:66:A9:E1

たぶんペアリングは問題なく終了すると思われる。

問題は、次のコネクト。筆者の場合は、bluetoothを再起動したりして、何度かチャレンジする中で、以下のとおり接続に成功した。

# connect EB:06:EF:66:A9:E1
Attempting to connect to EB:06:EF:66:A9:E1
[CHG] Device EB:06:EF:66:A9:E1 Connected: yes
[NEW] Endpoint /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep8 
[NEW] Endpoint /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep6 
[NEW] Endpoint /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep5 
[NEW] Endpoint /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep3 
[NEW] Endpoint /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep1 
[NEW] Transport /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep5/fd0 
Connection successful
[CHG] Transport /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep5/fd0 State: active
[CHG] Transport /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep5/fd0 Volume: 0x0050 (80)
[CHG] Device EB:06:EF:66:A9:E1 ServicesResolved: yes
[CHG] Transport /org/bluez/hci0/dev_EB_06_EF_66_A9_E1/sep5/fd0 State: idle

接続に成功したら、exitコマンドでbluetoothctlコマンドを抜ける。

# exit

毎回、Bluetoothctlコマンドを叩くのは大変なので、以下のスクリプトを利用すると良い。

$ cat bin/blule-connect
#/usr/bin/env bash
# bluetooth connect
bluetoothctl << EOC
connect EB:06:EF:66:A9:E1
quit
EOC

それでもコマンドを叩くのはちょっとという方は、以下のGUIをインストールすると良い。

筆者の場合、LXDEを使っているので、以下のとおり。

$sudo apt-get install blueman

gnome-bluetooth (for GNOME)

$ sudo apt install gnome-bluetooth

bluedevil (for KDE)

$ apt install bluedevil

bluemanをインストールした状態は、以下のとおり。

BluemanでX11の状態を確認

以上、他の方の参考になれば幸い。

関連ページ

DebianでノートPCのディスプレイを閉じてもサスペンドさせない設定

(2024-03-20 初稿)

たくさんのノートPCにDebianをインストールしてきたが、その度に検索して設定しているので、いい加減メモを残しておく。

参考にしたサイトは、以下のとおり。

/etc/systemd/logind.conf を以下のとおり変更する。

$ sudo vi /etc/systemd/logind.conf
#HandleLidSwitch=suspend  (変更前)
HandleLidSwitch=ignore       (変更後)

変更後は、以下のコマンドでサービスを再起動するか、または、PC自体を再起動する。

$ systemctl restart systemd-logind.service

今度こそ、検索しないで済むように…(笑)

関連ページ

 

API不要のtwikitで、tweetまたはtweetを取得する

(2024-03-18 初稿)

はじめに

X(旧 twitter)は、自分にとっては、ライフログを取る道具だったのだけど、度重なるAPIの変更で、最近は面倒になって放置中だった(笑)。

ところが、以下の記事を見つけて、ほんとに久しぶりにpythonを書いてみた。

この記事は、上記のサンプルや以下のドキュメントを見て、素人がpython3でtwikitを使って、tweetする方法と自らのtweetを取得するサンプルを記述する。

普段から、pythonを使っている方なら、もっと良いスクリプトが書けると思うので、あくまでもサンプルのつもり。

筆者はDebian 12(bookworm)を使っているが、twikitのインストールは、以下のとおり、とても行儀の悪い方法で行った。

$ pip3 install twikit --break-system-packages

皆さんは、仮想環境(venv)を作成してtwikitをインストールしてください。

作成したスクリプトについて

作成したスクリプトは、後述するが、基本的な使い方は以下のとおり。

コマンドライン引数

twk.py "つぶやきたいことをコマンドライン引数で指定する"

コマンドライン引数がないときは、自分のつぶやきを19個(?)取得する。countの数を変更しても、なぜか19個のtweetしか取得できない…^^;

筆者の場合は、ライフログ的な使い方を想定しているので、自分のつぶやきを取得することを重視している。

クッキー(cookie)

twikitは、毎回、ログイン環境を変更する仕様となっているようで、Xにログインするたびに、以下の通知やメールが届く。

Xの通知

ご利用のアカウント(@hogehoge)に新しい端末からログインがありました(2024年3月18日)。確認してください。

mailの警告

ご利用のアカウント(@hogehoge)に新しい端末からログインがありました。確認してください。

そこで、ドキュメントにもあるように、cookieを利用する。

cookieを保存しておき、次回起動時に読み込めば、ログインを省略してつぶやいたり、tweetを取得できたりする。

このスクリプトでは、cookieの保存場所を、以下にしてあるので、適当にディレクトリやファイル名を変更をしてください。

~/.config/twikit/twikit_cookies.json

その他

このスクリプトでは、以下の設定にしてあるので、こちらも適当に変更してください。

  auth_info_1='hogehoge',
  auth_info_2='hogehoge@example.com',
  password='yourpassword'

もう一つ、twikitを使う上で、重要なこと。

「あまり頻繁に利用しないこと。」頻繁に利用すると、エラーになる。

筆者の場合、最低でも5分間は間隔をあけて、利用するようにしている。

作成したスクリプト

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# tweet by twikit
# ver 0.01 2024-03-08 start
# ver 0.02 2024-03-18 save cookie
# ver 0.03 2024-03-18 tweet and get tweets

import os
import sys
from twikit import Client

cookie_file = 'twikit_cookies.json'
cookie_dir = os.path.expanduser("~/.config/twikit/")
cookie_path = cookie_dir + cookie_file
#print("cookie_fullpath= ", cookie_path )

if not os.path.isdir(cookie_dir):
    os.mkdir(cookie_dir)

client = Client('ja')

if os.path.isfile(cookie_path):
    client.load_cookies(cookie_path)
else:
    client.login(
        auth_info_1='hogehoge',
        auth_info_2='hogehoge@example.com',
        password='yourpassword'
    )
    client.save_cookies(cookie_path)

# 引数の数
#   2: tweetする
#   other: tweetを得る

args = sys.argv

if len(args) == 2:
    client.create_tweet(args[1])
else:
    user = client.get_user_by_screen_name('hogehoge')

    user_id = user.id
    #print(user_id)
 
    tweets = client.get_user_tweets(user_id, 'Tweets', count=20 )
    #print( len(tweets) )

    for tweet in tweets:
        print( '=============' )
        print( tweet.text )
        print( tweet.created_at )

スクリプトを実行するときには、実行権を与えてね。

$ chmod +x twk.py

おわりに

久しぶりに、pythonを使ったので、ネットでいちいち検索しながら作った。(^^ゞ

これくらいのスクリプトは、ネット検索しなくてもできるようになりたいけど、筆者の記憶力では無理っぽい…滝汗)

 

関連ページ

Amazonベーシック イーサネットアダプターはDebian 12(bookworm)で使える

(2024-03-12 初稿)

先日、ノートPCにLinuxをインストールしてサーバにしたいと頼まれたので、Debianをインストールした。

ただし、サーバとなると、やはり有線(Ethernetケーブル)でつなぐのが常識だが、最近のノートPCはEthernetの端子(RJ45)が付いていないものが多い。(T_T)

実のところ、筆者の持っているノートPCにもEthernetの端子が付いていない。

そこで、以下の商品が\1,404と安かったので、購入して試してみた。

予想通り、特に何も設定をせずに自動的に認識して、Ethernetが使えた。

参考までに、lsusbと/etc/network/interfacesを載せておく。

まずは、lsusb

(前略)
Bus 004 Device 002: ID 0b95:1790 ASIX Electronics Corp. AX88179 Gigabit Ethernet
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
(攻略)

どうも、内部は、ASIX Electronics Corp.の AX88179 ギガビットのよう

続いて、/etc/network/interfaces

(前略)
# The primary network interface
allow-hotplug enxa0cec8b97c53
# mod H.Yamada 2024-03-08
#iface enxa0cec8b97c53 inet dhcp
iface enxa0cec8b97c53 inet static
address 192.168.xxx.xxx
netmask 255.255.255.0
gateway  192.168.xxx.xxx
dns-nameservers 192.168.xxx.xxx

なお、Type C接続のものもあるので、お使いのPCに合わせて購入されたい。

関連ページ

Linuxインストール時Wi-Fiがつながらないときは、スマフォのUSBデザリングが便利

(2024-03-08 初稿)

職場のノートPC(Lenovo IdeaPad 1 14AMN7)にLinuxをインストールして欲しいと頼まれたので、Debianのインストールを行った。

このノートPCのネットワーク機器は、Ethernetは無く、Wi-Fiのみ。

Wi-Fiは、LenovoのWebサイトによると、RTL8822CE(RTL8852BE、どっちなのだろ(・・?) (後述のUbuntuでの認識は、RTL8852BEだった)。

筆者は、最低限のインストールを好むので、いつもDebian 12(bookworm)のnetinst版を利用させてもらっている。

いつもの様に、快調にインストールを進めたのだが、どうもWi-Fi機器を認識しない…

他のPCで、Web検索してGitやその他のドライバがあるのだが、いかんせんネットワークが使えないので、かなり不自由どころか、インストールもCUIでUSBを利用するのも困難な状況になってしまった。

そんな中で、Web検索中に以下のページを参照していたところ、以下の記述を見つけた。

インストールが完了した直後はWifiに繋げなかったので、
デザリングを使い、ターミナルでコマンドを打っていく。
(USBデザリングでWifiに繋いだスマホに繋ぐと便利!)

なるほど、そういう手があったか…

ということで、早速、試してみると、かなり便利。

スマフォをWi-Fiにつないでおけば、実質的にはパケットの消費が無くてドライバや各種ツールをダウンロードすることができる。

スマフォでUSBデザリングの設定

わがスマフォはAndroidだが、「設定」、「USBの設定」などと進めれば、「USBデザリング」の設定は簡単にできる。

で、問題のLinuxのインストールだが、Debianでドライバの更新などいろいろと試みたがうまくWi-Fi機器を認識させることはできず、結局、Ubuntuの22.04.4で問題なくを認識したので、今回はUbuntuをインストールして良しとした。

今後もLinuxインストール時にトラブルがあって、ネットワークが利用できない状況になったときは、スマフォのUSBデザリングを利用しようと思う。

どうしても、トラブルがあったときには慌ててしまって、デザリングを利用できるのを忘れてしまいがちなので、メモとして残しておく。

関連ページ

Debian 12(Bookworm)のnVIDIAグラフィックボード(GeForce GTX 1660 Ti)でデュアルモニター

(2024-03-07 初稿 - 2024-03-08 追記)

先日、新しくDellのディスプレイを購入したことは、以下に記事にした。

これまで使っていた24インチのディスプレイも、接続はやや旧型だがまだまだ十分現役で使える。

そこで、Debian 12(Bookworm)をインストールして使っているデスクトップPCに接続して、デュアルモニター(デュアルディスプレイ)として使ってみることとした。

DebianをインストールしているデスクトップPCには、nVIDIAグラフィックカード(GeForce GTX 1660 Ti)が付いており、インストールした状態のnouveaのドライバではうまく動作しなかったことと、グラボのDisplay PortをHDMIに変換する必要があった。

したがって、この記事では、以下の2点を主に報告する。

  • グラフィックドライバーを、nouveaではなく、nvidia-driverに変更する
  • 接続端子の変換コネクタまたは変換ケーブルで、Display PortをHDMIに変換する

Debianでデュアルモニタ

ドライバの変更

実は、ツイートにあるように、2023年11月3日に、nvidia-driverをインストールしたのだけど、うまく動作できないとつぶやいている。

昨年11月時点では、失敗したけど、現在は無事に動作するし、以下のWikiには、失敗した場合のアンインストール方法も記載されている。

筆者が失敗したときは、アンインストール方法がなくて、再度クリーンインストールするはめになった。(T_T)

そんなこともあり、ずっとドライバとしてnouveaを使っていた。

具体的なインストール方法は、以下のサイトに記述があるので、参考に行ってほしい。

以下、再掲になるので、簡単に。

グラフィックボードを確認して、ドライバの確認。

$ sudo apt install nvidia-detect
$ nvidia-detect
Detected NVIDIA GPUs:
08:00.0 VGA compatible controller [0300]: NVIDIA Corporation TU116 [GeForce GTX 1660 Ti] [10de:2182] (rev a1)
Checking card:  NVIDIA Corporation TU116 [GeForce GTX 1660 Ti] (rev a1)
Your card is supported by all driver versions.
Your card is also supported by the Tesla 470 drivers series.
It is recommended to install the
    nvidia-driver
package.

カーネルヘッダーのインストール

$ sudo apt install linux-headers-amd64

ドライバとその他ファームウェアのインストール

$ apt install nvidia-driver firmware-misc-nonfree

念のために、BIOSでsecure bootがOffであることを確認してね。

接続方法

nVIDIAのグラフィックボードは、ビデオの出力が Display Port、HDMI、DVIがそれぞれ1つずつある。

一方、接続するディスプレイは、HDMIとD-sub15しか付いていない。

したがって、Display PortをHDMIに変換、または、DVIをD-sub15に変換する必要があるが、音声の出力等も考えて、Display PortをHDMIに変換することにした。

急いで確認したかったこともあり、近所のケーズデンキサンワサプライのkc-DPHDa20を4,159円で購入したが、Amazonまたは楽天市場の方が安かった。(^_^;)

設定(lxrandr)

前述の接続のところでは、詳しく書かないが実はグラフィックドライバを更新する前にテストして、なかなかデュアルモニタにならなくて、ようやくデュアルモニタに出力できたら、今度は、同じ画面しか映らなくて… 結構、半日以上あーでもないこーでもないと苦戦して、あっ、ドライバの問題かも知れないと気がついて、ようやくうまく行くようになった。

設定は、現状、左右で大きな画面として使っているが、DebianLXDEを使っている場合(かなりニッチかな ^^;)は、以下のとおりで設定できる。

メニューから「設定」、「モニタの設定」を選択する、または、lxrandrを起動。

位置を「デフォルト」、「右」、「上」、「左」、「下」のいずれかを選択する。

筆者の場合は、HDMI 0のモニタを、下図のとおり右側に配置している。

「モニタの設定」、lxrandrの設定

インプレッション

ディスプレイドライバを交換してから、デュアルモニタにしても、動作が軽快になった気がする。

やはり、ディスプレイドライバはすべての表示に関連するので、僅かな差が積もり積もって感じられるようになるのかも知れない。

筆者のように、nVIDIAのドライバのインストールでトラブって、そのままnouveaを利用している方もいるかも知れないが、今のDebianなら安心して移行できるので、早めに移行することをお薦めする。

(2024-03-08追記)

以下の記事によると、3月末くらいで生産終了とのこと。せっかくアップしたばかりなのに… (アップがおそすぎる(笑) )

新たに中国のPCパーツ情報サイト「Board Channels」に投稿された情報によると、NVIDIAは2024年第1四半期(1月~3月)を最後にGeForce GTX 16 シリーズの生産を終了することを決定したとのこと。

(追記終了)

関連ページ