gzに圧縮されたファイルを解凍せずに中身を確認する方法[zgrep]

固めたログファイルを解凍せずに、確認したいときのための備忘録です。

目的

linuxサーバー上で、gzで圧縮、固めたファイルの中身を確認したい。

zgrep

zgrepコマンドを使用すれば、.gzで圧縮されたファイル内を検索することが可能です。

使い方は、通常のlinuxコマンドのgrepとほぼ一緒です。

zgrep 検索するキーワード 検索対象のgzファイル

複数ファイル

複数ファイルを固めたtar.gzファイルを、zgrepすると以下のようなメッセージが表示されます。

Binary file (standard input) matches

オプション-aをつけることで、中身を読み込むことが可能です。

また、リダイレクトを使用することで、一部を抽出したファイルの作成も可能です。

# zgrep 検索するキーワード 検索対象のgzファイル >> 抽出先ファイル
  • 抽出先のファイル名を.gzにしても圧縮されないので、圧縮したい場合は別途gzipコマンドを使用します。

zcat

.gzファイル全体を表示したい場合はzcatを使用します。
複数ファイルを固めたtar.gzファイルは、中身を見れませんでした。

# zcat 閲覧対象のファイル

grep -Z

調べたところgrep -Zでもzgrepと同じことができるようです!
grep -Zaで、tar.gzファイルも検索可能です。

zgrepの存在意義が。。 ちなみに、cat -Zはさすがに存在していませんでしたw

参考

以下のサイト様を参考にさせていただきました。

https://nxmnpg.lemoda.net/ja/1/zgrep

【 zcat 】コマンド/【 zless 】コマンド/【 zmore 】コマンド/【 zgrep 】コマンド/【 zcmp 】コマンド/【 zdiff 】コマンド/――gzipで圧縮されたファイルを操作する:Linux基本コマンドTips(250) - @IT

JAWS-UG 初心者支部に参加してきました!

JAWS(日本AWSのグループ)の初心者支部Fin-JAWSコラボ&ミニハンズオン会に参加してきました。

AWSアカウントを作ったら最初にやるべきこと-セキュリティ編-

以下を使用したミニハンズオンでした。

qiita.com

アカウント作った際にやるべきことは、以下のためだそうです。 - 不正アクセスの対策 - もしもの時のログの有効化 - 不正アクセスされた際に通知させる

そのために、以下に記載されている20項目を、AWSアカウントを作ったら最初にやるべきだそうです。

dev.classmethod.jp

時間の関係上、以下の設定を実施しました。 - ルートアクセスキーの削除 - ルートアカウントは全てのサービスへのアクセスが出来てしまうため、ルートアカウントは使用せず、IAMユーザーを使用しましょう。

  • ルートアカウントのMFA有効化

    • もしメールアドレスとパスワードが流出してしまっても、ログインできないように多要素認証を有効化しておきます。
  • パスワードポリシーの変更

    • デフォルトの設定は「6文字以上」となっていますが、もう少し複雑なパスワードポリシーに変更します。
  • IAMグループの作成

    • IAMグループを作成することで、権限管理がしやすくなります。
  • IAMユーザーの作成

    • ルートアカウント以外にログインできるアカウント(IAMユーザー)を作成します。
  • CloudTrailの有効化

    • 有効化しておくと、いつ、どのアカウントが、どのような操作を行ったかを確認することが出来ます。
  • GuardDutyの有効化

    • GuardDutyはAWSアカウントやAWSリソースに対する不審なアクティビティを検知/通知してくれるサービスです。

Fin-JAWSの紹介と金融の現状

元々、金融業界では他の業界と比較して、クラウド化の動きは鈍かったそうです。
特に、勘定系(預金、貸付、為替)と呼ばれるシステムは、オンプレの銀行がほとんど。

しかし、大阪リージョンが開設されることが、発表されたことで今までクラウド化されてこなかった勘定系の業務システムもクラウド化を進める動きがあるそうです。

www.publickey1.jp

aws.amazon.com

セキュリティが重視される金融業では、国内でマルチリージョン構成ができるのはかなり大きいようです。

データはどこからくるの?〜AWSとオンプレとの違いで学んだあれやこれ〜

発表された資料は以下になります。

20200129 jawsug bgnr22

検証環境の出来事だったので大きな問題にはならなかったそうですが、Lambdaの同時実行上限には気をつけましょう。。

以下を参考させていただくと、CloudWatchメトリクスから同時実行数を確認できる様です。

oji-cloud.net

FISCから学ぶAWSセキュリティことはじめ

発表された資料は以下になります。

FISCから学ぶAWSセキュリティことはじめ.pdf - Speaker Deck

FISCとは・・金融情報システムに関連する様々な問題についての調査研究を行う公益財団法人のことです。

FISCが金融機関等コンピュータシステムの安全性基準を提供していて、金融業界は、FISCガイドラインを意識した設計が重要視されているそうです。

AWSでも、FISCガイドラインに準拠したリファレンスガイドが提供されています。

aws.amazon.com

そして、AWSと利用者側の責任に関する線引きも明確にされています。お客様がAWSを利用される場合には障害発生時の責任、対応はAWSかお客様か明確にし、要件に応じて、対策や確認が必要だそうです。

aws.amazon.com

最新のFISCガイドライン(9版)に対応した、AWSのリファレンスガイドはまだ発表されていないそうです。

マルチアカウント運用のはじめかた(Japan Degital Design)

発表された資料は以下になります。

JAWS-UG初心者支部 - 2020-01-29 - マルチアカウント運用のはじめかた

AWS Organizationsを利用すると、

  • 1つのAWSアカウントにルートとして、複数のAWSアカウントを子アカウントとして管理できる。
  • AWSアカウントの利用料金を一括請求で払える。

また、OUで階層化、子アカウントの権限管理できます。

設定の流れは、

  1. ルートになるアカウントを決める
  2. AWS Orgaizationsを有効化する
  3. 既存のAWSアカウントを子アカウントに招待
  4. OUでAWSアカウントの整理
  5. 新しいAWSアカウント追加時はルートで行う

そのほかのポイント

  • なるべくアカウントは共有しない
  • 組織単位ではなく、AWS準拠でグループを分けたほうが良い
  • 1アカウント 1用途を基本にして考える

感想

ソリューションアーキテクトの資格を取得してから、AWSとどう関わっていこうか悩みどころでしたが、もっと触ってみようというモチベーションをもらえたので参加してよかったです!

次回(2/19)も参加しようと思います!

CentOS7.7にWindowsServer2016の隠しフォルダをマウントしてみた。

目的

CentOS7.7にWindowsServer2016の隠しフォルダをマウントしたい。

環境情報

Azure上に以下のOSで仮想サーバを計2台用意しました。 - Linux OS:CentOS7.7
- Windows OS:WindowsServer2016

インスタンス情報 - スポットインスタンス - 最小スペックのインスタンス - 2つのサーバ間のNSGはガバガバです。

検証

WindowsServer側作業

1. ログインし、日本語化します。

  • リモートデスクトップで、WindowsServerのグローバルIPにログンします。
  • スタートメニューからControl Panelを開きます。

f:id:Tk24:20200124160158j:plain

  • Clock, Language, and Regionをクリックします。

f:id:Tk24:20200124160223j:plain

  • Languageをクリックします。

f:id:Tk24:20200124160244j:plain

  • Add a languareをクリックします。

f:id:Tk24:20200124160258j:plain

  • 日本語を選択します。

f:id:Tk24:20200124160316j:plain

  • Languageの画面に日本語が追加されたら、選択し`Move upをクリックします。

f:id:Tk24:20200124160357j:plain

  • 日本語が最上段に来たら、右側のOptionsをクリックします。

f:id:Tk24:20200124160419j:plain

  • Download and install language packをクリックして、インスールが完了するのを待ちます。

  • インストールが完了すると、Installation complateされるのでcloseをクリックします。

  • Languageの画面に戻るため、`Clock, Language, and Regionに移動します。

  • Regionをクリックします。

  • Regionの設定画面が開くため、Locationタブをクリックしす。

  • Home location:Japanに変更する。

f:id:Tk24:20200124162722j:plain

  • Administrativeタブに移動し、Copy settingをクリックします。

f:id:Tk24:20200124162704j:plain

  • Welcom screen and system accountsNew user accountsにチェックを入れ、OKをクリックします。

f:id:Tk24:20200124162625j:plain

  • 再起動を促されるためRestart nowをクリックします。  

f:id:Tk24:20200124162606j:plain

日本語化完了です!

再起動後、表示される時間を日本時間に変更する場合
  • 画面右下の時刻を右クリックする。

  • 日付と時刻の調整をクリックします。

  • タイムゾーン(UTC+09:00)大阪、札幌、東京を選択します。

f:id:Tk24:20200124163112j:plain

2. フォルダ共有用のユーザーの作成

adminユーザーでも共有できますが、できる限り最小の権限で共有したほうが安全です。
目的に沿ったユーザで共有したいので、今回はファイル共有用の一般ユーザーを作成します。

  • スタートメニューからコントロールパネルを開きます。

  • ユーザーアカウントをクリックします。

  • アカウントの種類の変更をクリックします。

f:id:Tk24:20200124191151j:plain

  • ユーザーアカウントの追加をクリックします。

f:id:Tk24:20200124191309j:plain

  • 各項目に入力し、次へをクリックします。

f:id:Tk24:20200124191636j:plain

  • 設定内容が、問題がなければ完了をクリックします。

f:id:Tk24:20200124191703j:plain

ユーザーの作成完了です!

3. 共有する隠しフォルダを作成する

  • Cドライブ直下にbackupというフォルダを作成します。
  • 作成したフォルダを右クリックし、プロパティをクリックします。

f:id:Tk24:20200124163629j:plain

  • 共有タブをクリックし、詳細な共有をクリックします。

f:id:Tk24:20200124163745j:plain

  • このフォルダーを共有するにチェックを入れ、共有名の最後に$マークを入力します。
    $を末尾に入力することにより隠しファイル扱いになります。

f:id:Tk24:20200124164258j:plain

  • 最下部のOKをクリックします。
  • 共有をクリックします。

f:id:Tk24:20200124170401j:plain

  • 作成したユーザーを入力し、追加をクリックします。
  • ユーザーが追加されたことを確認し、共有をクリックする。

f:id:Tk24:20200124165940j:plain

  • 終了をクリックする。
  • ネットワーク パスを控えておきます。 ※CentOSから、マウントする際に使います。

f:id:Tk24:20200124170401j:plain

  • 閉じるをクリックする。
  • 確認用にbackupフォルダ内にtest.txtを作っておきます。

これで、windows側の設定は完了です!

CentOS側作業

  • teratermなどを使って、CentOSサーバーのグローバルIPにログンします。
  • rootユーザーになります。
$ sudo su -
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for ユーザー名: 
#
  • 必要なパッケージをインストールします。
    linux側からマウントするだけであれば、sambaはいらないかもしれませんが念のため。
# yum install -y samba-client cifs-utils

# rpm -qa | grep samba
samba-client-4.9.1-10.el7_7.x86_64
samba-common-4.9.1-10.el7_7.noarch
samba-client-libs-4.9.1-10.el7_7.x86_64
samba-common-libs-4.9.1-10.el7_7.x86_64

# rpm -qa | grep cifs
cifs-utils-6.2-10.el7.x86_64
# mkdir ./test /mnt/backup

# ls -l ./ /mnt
./:
drwxr-xr-x. 2 root root    6 Jan 24 06:06 test
/mnt:
drwxr-xr-x. 2 root root    6 Jan 24 06:21 backup
  • 資格情報をもたせたファイルを作成します。
# cd test

# vim mnt-info

以下の情報を記載し、保存します。
username=Windowsサーバで作成したユーザー名
password=パスワード
  • マウント前の状態を確認します。
# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        1.7G     0  1.7G   0% /dev
tmpfs           1.7G     0  1.7G   0% /dev/shm
tmpfs           1.7G  9.0M  1.7G   1% /run
tmpfs           1.7G     0  1.7G   0% /sys/fs/cgroup
/dev/sda2        30G  1.5G   29G   5% /
/dev/sda1       497M   64M  433M  13% /boot
/dev/sdb1       6.8G   32M  6.4G   1% /mnt/resource
tmpfs           343M     0  343M   0% /run/user/1000
  • マウントします。
mount.cifs //ホスト名/backup/ /mnt/backup -o credentials=/root/test/mnt-info,file_mode=0755,dir_mode=0755
  • マウントの状態を確認します。
# df -h
Filesystem        Size  Used Avail Use% Mounted on
devtmpfs          1.7G     0  1.7G   0% /dev
tmpfs             1.7G     0  1.7G   0% /dev/shm
tmpfs             1.7G  9.0M  1.7G   1% /run
tmpfs             1.7G     0  1.7G   0% /sys/fs/cgroup
/dev/sda2          30G  1.5G   29G   5% /
/dev/sda1         497M   64M  433M  13% /boot
/dev/sdb1         6.8G   32M  6.4G   1% /mnt/resource
tmpfs             343M     0  343M   0% /run/user/1000
//ホスト名/backup$  127G   12G  115G  10% /mnt/backup
  • WindowsServerに作成したファイルを参照します。
# cd /mnt/backup/
# ls -l
-rwxr-xr-x. 1 root root 4 Jan 24 05:49 test.txt

見れました!マウント完了です!!

感想

今まで、Windowsサーバーはほとんど触ってこなかったのですが、意外と簡単にできましたね!

Windowsサーバーを最初に立ち上げたときが、重すぎて一番困惑しました。。
しばらく放っておいたら安定ましたが。。

Azureは同じ仮想ネットワーク(VNet)であれば、何もしなくても名前解決できるんですね!
便利!

MarkdownをPDF化する際にページ数を出力する方法

目的

Markdown で記載した資料をPDF化した際にページ番号をつけたい。

環境情報

OS:Windows10
Visual Studio Code:1.41.1

やり方

1.拡張機能の[Markdown PDF]をインストール。
・サイドバーの[Extentions]をクリックします。
 表示された検索バーに、[Markdown PDF]と入力します。
 検索結果に表示された[Markdown PDF]をクリックし、インストールします。

f:id:Tk24:20200122154129j:plain

2.PDFファイル作成
・「Ctrl」+「Shift」+「P」を押し、「export」と入力します。
 表示された「Markdown PDF:Export(PDF)」を選択します。 f:id:Tk24:20200122154448j:plain

・もしくは、右クリックからでも選択できます。
f:id:Tk24:20200122154459j:plain

PDFが出力されたので、確認します。
こんな感じに、ページ数が出力されているはずです!

f:id:Tk24:20200122155742j:plain

注意

MarkdownをPDFかする想定で書いた際に、改ページするために以下のcssコードを利用すると思います。

<div style="page-break-before:always"></div>

その際に、次の一行を空行にしないとMarkdownの記載がおかしくなる場合があるみたいです。
私の場合は、#などがそのまま出力されていました。

ヘッダー、フッターの編集方法。

デフォルト設定のままだと、ヘッダーに「ファイル名」「出力日時」、フッターに「ページ番号」が入ります。しかし、必要のない情報は出力したくないのでヘッダーとフッターの設定を編集します。

  • 「ファイル」→「基本設定」→「設定」をクリックします。
    設定画面が開いたら、以下のどちらかを入力します。
    ・ ヘッダーを編集したい場合:headerTemplate
    ・ フッターを編集したい場合:footerTemplate

    「setting.jsonで編集」をクリックします。

f:id:Tk24:20200122155900j:plain

 以下の情報を元にヘッダー、フッター設定を変更します。

  • ヘッダーのデフォルト設定のパラーメータ情報。
    <span class='date'></span> : 日付
    <span class='title'></span> : Markdown ファイル名
    <span class='url'></span> : Markdown フルパスファイル名

  • 実際のデフォルト設定(ヘッダー)
    "markdown-pdf.headerTemplate": "<div style=\"font-size: 9px; margin-left: 1cm;\"> <span class='title'></span></div> <div style=\"font-size: 9px; margin-left: auto; margin-right: 1cm; \"> <span class='date'></span></div>",

  • フッターのデフォルト設定のパラーメータ情報。
    <span class='pageNumber'></span> : 現在のページ番号
    <span class='totalPages'></span> : ドキュメントの総ページ数

  • 実際のデフォルト設定(ヘッダー)
    "markdown-pdf.footerTemplate": "<div style=\"font-size: 9px; margin: 0 auto;\"> <span class='pageNumber'></span> / <span class='totalPages'></span></div>",

私はヘッダーが必要なかったので、丸ごと削除しました!

参考

https://github.com/yzane/vscode-markdown-pdf/blob/master/README.ja.md#%E6%A9%9F%E8%83%BD

Python 100本ノックを始めました。 10本目

使用するファイルが文字化けしていたため、以下のサイトから最新の気温データをコピペして「hightemp.txt」を作成しました。
https://www.data.jma.go.jp/obd/stats/etrn/view/rankall.php

10. 行数のカウント

問題

  • 行数をカウントせよ.確認にはwcコマンドを用いよ

イメージした処理の流れ

linuxコマンドの「wc」を用いてカウントするのか、別の方法でカウントした結果を「wc」コマンドの結果と比較して確認するのか、よくわからなかったので両方作成しました!

linuxコマンドを使用しない行数カウント

①行数をカウントするファイル名を取得
②withを使用してファイルの読み込み
③ファイルに含まれる改行コードをカウント
④結果を出力

linuxコマンドを使用する行数カウント

⑤wcコマンドの実行
⑥wcコマンドの出力結果を加工
※-lオプションをつけても「行数 + ファイル名」で出力されるため
⑦結果を出力

作成したコード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#行数をカウントせよ.確認にはwcコマンドを用いよ

import subprocess

#ファイル名を取得(①)
filename = input("行数をカウントするファイル名を指定してください:")

#linuxコマンドを使用しない行数カウント
with open(filename,"r") as f: #(②)
        #filename内の改行コードをカウント(③)
        num = f.read().count("\n")
        print("{} は {} 行記載されています。(python)".format(filename, num)) #(④)

#wcコマンドを使用した行数カウント
res = subprocess.run(['wc', '-l',filename,], encoding='utf-8', stdout=subprocess.PIPE) #(⑤)
#wcコマンドの結果をスペースで区切ってリストに追加(⑥)
line_num = res.stdout.split(" ")
#行数が表示される部分を抽出して表示(⑦)
print("{} は {} 行記載されています。(linuxコマンド)".format(filename, line_num[0]))

実行結果

行数をカウントするファイル名を指定してください:hightemp.txt
hightemp.txt は 21 行記載されています。(python)
hightemp.txt は 21 行記載されています。(linuxコマンド)

感想

この記事を書いていて、改行コードをカウントするだけでは「行数-1」になってしまうのではないか?という疑問がわきました。

上記の疑問を解決するために調べた結果、catに-eをつけると改行コードが見えることを知りました。
「LF」を「$」、「CR」を「M」で表示するらしいです。
cat -e hightemp.txtで確認したところ、以下のような結果が返ってきました。

# cat -e hightemp.txt
M-eM-^_M-<M-gM-^NM-^IM-gM-^\M-^L M-gM-^FM-^JM-hM-0M-7 * 41.1    2018-7-23$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-gM->M-^NM-fM-?M-^C   41.0    2018-8-8$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-iM-^GM-^QM-eM-1M-1   41.0    2018-8-6$
M-iM-+M-^XM-gM-^_M-%M-gM-^\M-^L M-fM-1M-^_M-eM-7M-^]M-eM-4M-^N  41.0    2013-8-12$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-eM-$M-^ZM-fM-2M-;M-hM-&M-^K  40.9    2007-8-16$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-dM-8M--M-fM-^]M-!     40.8    2018-8-23$
M-fM-^]M-1M-dM-:M-,M-iM-^CM-= M-iM-^]M-^RM-fM-"M-^E     40.8    2018-7-23$
M-eM-1M-1M-eM-=M-"M-gM-^\M-^L M-eM-1M-1M-eM-=M-" *      40.8    1933-7-25$
M-eM-1M-1M-fM-"M-(M-gM-^\M-^L M-gM-^TM-2M-eM-:M-^\ *    40.7    2013-8-10$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-eM-/M-:M-fM-3M-^J     40.6    2019-8-15$
M-eM-^RM-^LM-fM--M-^LM-eM-1M-1M-gM-^\M-^L M-cM-^AM-^KM-cM-^AM-$M-cM-^BM-^IM-cM-^AM-^N   40.6    1994-8-8$
M-iM-^]M-^YM-eM-2M-!M-gM-^\M-^L M-eM-$M-)M-gM-+M-^\     40.6    1994-8-4$
M-eM-1M-1M-fM-"M-(M-gM-^\M-^L M-eM-^KM-^]M-fM-2M-<      40.5    2013-8-10$
M-eM-1M-1M-eM-=M-"M-gM-^\M-^L M-iM-<M- M-cM-^BM-1M-iM-^VM-"     40.4    2019-8-15$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-dM-8M-^IM-fM-^]M-!    40.4    2018-8-23$
M-eM-^_M-<M-gM-^NM-^IM-gM-^\M-^L M-hM-6M-^JM-hM-0M-7    40.4    2007-8-16$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-iM-+M-^XM-gM-^TM-0 *  40.3    2019-8-14$
M-fM-^DM-^[M-gM-^_M-%M-gM-^\M-^L M-eM-^PM-^MM-eM-^OM-$M-eM-1M-^K *      40.3    2018-8-3$
M-gM->M-$M-iM-&M-,M-gM-^\M-^L M-iM-$M-(M-fM-^^M-^W      40.3    2007-8-16$
M-gM->M-$M-iM-&M-,M-gM-^\M-^L M-dM-8M-^JM-iM-^GM-^LM-hM-&M-^K   40.3    1998-7-4$
M-fM-^DM-^[M-gM-^_M-%M-gM-^\M-^L M-fM-^DM-^[M-hM-%M-?   40.3    1994-8-5$

最終行まで、改行が入っていますね。
これであれば、カウント間違いはなさそうです。

ちなみに、-e無しは以下です。

# cat hightemp.txt
埼玉県 熊谷 *   41.1    2018-7-23
岐阜県 美濃     41.0    2018-8-8
岐阜県 金山     41.0    2018-8-6
高知県 江川崎   41.0    2013-8-12
岐阜県 多治見   40.9    2007-8-16
新潟県 中条     40.8    2018-8-23
東京都 青梅     40.8    2018-7-23
山形県 山形 *   40.8    1933-7-25
山梨県 甲府 *   40.7    2013-8-10
新潟県 寺泊     40.6    2019-8-15
和歌山県 かつらぎ       40.6    1994-8-8
静岡県 天竜     40.6    1994-8-4
山梨県 勝沼     40.5    2013-8-10
山形県 鼠ケ関   40.4    2019-8-15
新潟県 三条     40.4    2018-8-23
埼玉県 越谷     40.4    2007-8-16
新潟県 高田 *   40.3    2019-8-14
愛知県 名古屋 * 40.3    2018-8-3
群馬県 館林     40.3    2007-8-16
群馬県 上里見   40.3    1998-7-4
愛知県 愛西     40.3    1994-8-5

ただ、余りにも強引なやり方すぎたので、ほかのやり方を少し調べました。
そうすると、以下のような書き方を見つけ、こちらでカウントするほうがスマートで確実だなと思いまいした。

num_lines = sum(1 for line in open(filename))

改行コードはOSごとに違うので、それに影響されない方法が良いですよね。。

Python 100本ノックを始めました。 9本目

09. Typoglycemia

問題

  • スペースで区切られた単語列に対して,各単語の先頭と末尾の文字は残し,それ以外の文字の順序をランダムに並び替えるプログラムを作成せよ. ただし,長さが4以下の単語は並び替えないこととする.適当な英語の文 (例えば"I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind .") を与え,その実行結果を確認せよ.

イメージした処理の流れ

①文章を単語ごとにリスト化
②並べ替える対象の文字を抽出し、ランダム文字列一覧を作成
③文字数でフィルター
④③で抽出した文字から、並べ替える文字数分ランダムに選択する
⑤④で使用した文字を、ランダム文字列一覧から削除
⑥「先頭文字 + ④で作成したランダム文字列 +末尾」を作成する
⑦リスト内の並べ替え前の文字列と、並べ替え後の文字列を入れ替える
⑧③-⑦をリスト内の全単語でループ処理
⑨文章として表示

作成したコード

import random

def str_random(n):
    a = "" #並べ替え用文字列を格納
    b = [] #単語へ置き換える文字を格納

    #文章をリストに変換(①)
    str_list = n.split(" ")

    #先頭と末尾以外の並べ替える文字の候補(a)を作成(②)
    for x in range(len(str_list)):
        if len(str_list[x]) > 3:
            a += str_list[x][1:-1]

    for x in range(len(str_list)): #⑧
        c = "" #先頭と末尾以外の文字列を入れ替えた単語を格納
        if len(str_list[x]) > 3: #③
            #置き換える文字(b)を候補(a)から抽出(④)
            b = random.sample(a, k=len(str_list[x])-2)
            for y in b:
                #置き換える文字(b)をリストから文字列に変換
                c += y
                #使用した並べ替え候補をリスト(a)から削除(⑤)
                a = a.replace(y, "", 1)
            #並べ替えた単語を作成(⑥,⑦)
            str_list[x] = str_list[x][0]  + c + str_list[x][-1]
    #入れ替えた単語を表示する(⑨)
    print(" ".join(str_list))

str_random("I couldn't believe that I could actually understand what I was reading : the phenomenal power of the human mind ."))

実行結果

I cmemdeot bilniue ttht I cewod auoeaeny ueislvr'nd wnat I was rlhndag : the pnolcathal puenr of the hlaun madd .

感想

最初、処理④の時にrandom.choicesを使用していて同じ文字列が重複して選ばれていました。( ’ が複数出てきていて気が付きました。)

抽出する際に重複させない場合は、random.samplesを使用することを認識しました。

しかし、次の単語を作成する前に使用した文字列を削除する必要性に気が付いたので以下のような処理に変更しました。

for y in b:
    #置き換える文字(b)をリストから文字列に変換
    c += y
    #使用した並べ替え候補をリスト(a)から削除(⑤)
    a = a.replace(y, "", 1)

結果、一文字ずつ処理をしているのでrandom.samplesに変更した意味はなくなりました。。

ただ、この処理はなんだか野暮ったい感じに見えます。
もっと良い処理方法はないものか。。

Python 100本ノックを始めました。 8本目

経緯

Pythonのコードを書く練習がしたかったので、以下の100本ノックを始めることにしました。 全部をやるかはわかりませんが、コツコツやっていきたいと思います。

ブログには、少し詰まった個所などをアウトプットしていきます。

08. 暗号文

問題

  • 与えられた文字列の各文字を,以下の仕様で変換する関数cipherを実装せよ.
    ・英小文字ならば(219 - 文字コード)の文字に置換
    ・その他の文字はそのまま出力
    この関数を用い,英語のメッセージを暗号化・復号化せよ.

イメージした処理の流れ

①対象の文字列をリスト化
②英子文字のみに絞るためフィルター
③英子文字の暗号化
④暗号化した文字を複合化
⑤複合化した文字を文字列として再生成

作成したコード

import string

def cipher(n):
    #変数
    str_list = []
    enc_str =""

    #暗号化対象の文字列をリストに追加(①)
    for x in n:
        str_list.append(x)

    #暗号化
    for x in range(len(str_list)): 
        #英小文字のみフィルターし、暗号化→複合化
        if str_list[x] in string.ascii_lowercase: #(②) 
            str_list[x] = chr(219 - ord(str_list[x])) #(③,④)
    
    #文字列を生成(⑤)
    print("".join(str_list))

cipher("あAa1Bb2Cc3Dd4Ee5いFf6Gg7Hh8Ii9Jj10うKk11Ll12Mm13Nn14Oo15えPp16Qq17Rr18Ss19Tt20おUu21Vv22Ww23Xx24Yy25Zz26")

実行結果

あAz1By2Cx3Dw4Ev5いFu6Gt7Hs8Ir9Jq10うKp11Lo12Mn13Nm14Ol15えPk16Qj17Ri18Sh19Tg20おUf21Ve22Wd23Xc24Yb25Za26

感想

そもそも問題文の「英小文字ならば(219 - 文字コード)の文字に置換 」が理解できなくて、219に該当する文字コードは何かを調べていました。

認識の間違いに気が付いても、次は複合化の意味を取り違えて、折角暗号化した文字列を元の状態に戻して出力させようとしていました。。

他には、処理の③,④で使用している ordchrアスキーコード(ascii)から文字列へ相互に変換できることは知りませんでした。勉強になりました。