1. tera1707

    Posted

    tera1707
Changes in title
+[バッチ] for と 「/f "tokens=〇"」 を使って、スペース区切りの文字列の必要列だけ取り出す
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,115 @@
+# やりたいこと
+各種コマンドを使って取ってきた情報から、1行丸ごとではなく、必要な情報というか要素だけ取り出したい。
+
+例えば、[以前](https://qiita.com/tera1707/items/e1a73f09ebc14fd2b5f8)試した`dir`で一覧として出るファイル・フォルダから`find`でいるものだけ絞ったあと、そのファイル・フォルダの更新時間を取り出したい、などの場合。(下記のイメージ)
+
+![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/99425c34-6bd2-8402-eeac-93c0eaeb5bc9.png)
+
+# やり方
+`for`文を使う。
+
+# forの原型
+
+```
+for [オプション] %%アルファベット1文字 in (ループの対象) do (
+ 処理
+)
+```
+
+この中の「ループの対象」には、例えばdirなどのコマンドを入れることができる。
+そのコマンドの結果が「%%アルファベット1文字」に入るイメージ。
+**(forといえばループだが、ループのためではなく「コマンドの戻り値を採る」ために使う)**
+
+# 具体的な例
+今回は、dirで取得したファイル・フォルダ一覧から「target.txt」の行を取り出し、その中から時間の文字列を取り出す、ということをする。下記のバッチで取り出せる。
+
+```
+@echo off
+FOR /F "tokens=2" %%A IN ('dir ^| find "target.txt"') DO (
+ ECHO update time is %%A
+)
+pause
+```
+
+```output.txt
+update time is 22:09
+```
+
+# 説明
+
+### トークン
+
+`for`のオプション`/f`には、「トークン」というものを指定できる。
+トークンには、下記のようなものがある。[参考](https://qiita.com/sawa_tsuka/items/67be34bab1fdf3fb87f9#6for%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AE%E6%A7%8B%E6%96%87-f%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%82%92%E4%BB%A3%E5%85%A5%E3%81%99%E3%82%8B-)
+
+- tokens= 何番目のトークンを指定するか?
+- delims= トークンの区切り文字を指定
+- eol= この文字から始まる行を無視
+- skip= 先頭から指定された行数、スキップする。
+- usebackq コマンドの出力を対象にする
+
+その中の`tokens`を使用する。
+
+### tokens
+`tokens`に2を指定すると、「スペースで区切られた文字列の2番目のものをとって、%%Aに入れる」という意味になる。
+
+上の例だと、`dir ^| find "target.txt"`でとってきた1行の文字列の、スペース区切りの2番目を採ることになる。
+![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/d3a530af-f723-7d52-0dae-e7215b61adba.png)
+
+### ループの対象(=コマンド)
+下記のかっこの中には、戻り値を取得したいコマンドを書く。
+
+```
+FOR /F "tokens=2" %%A IN ('dir ^| find "target.txt"') DO (
+```
+
+※注意としては、パイプを使って`dir`→`find`とデータを渡したいときには、「|」の横に「^」をつけないと動かなかった。
+
+### 処理
+コマンドの結果が`%%A`に入ってくるので、それを使った処理を書く。
+この場合は、%%Aに時間の文字列が入ってくる。
+
+```
+ECHO update time is %%A
+```
+
+# 実際にこれを使ったとき
+実際には、下記のような場面でこの方法を使った。
+
+- diskpartで、ボリュームの一覧を取得
+- その中で「MYVOLUME」というラベル名のボリュームを探す。
+- そのボリュームに「T]というドライブ?レターを付与する
+- そのドライブ(Tドライブ)に移動(cd)する
+
+```
+@echo off
+
+ECHO list volume > %~dp0listvolume.txt
+diskpart /s %~dp0listvolume.txt
+
+
+FOR /F "tokens=2" %%A IN ('diskpart /s %~dp0listvolume.txt ^| find "MYVOLUME"') DO (
+ ECHO select volume=%%A > %~dp0selectvolume.txt
+)
+
+ECHO assign letter=T > %~dp0selectvolume.txt
+del %~dp0selectvolume.txt
+del %~dp0listvolume.txt
+
+cd /d T:
+
+pause
+```
+
+※各コマンド(diskpartなど)については割愛。
+
+※diskpartでラベル名とそのボリューム番号は取れてるのに、ボリューム番号だけ取得できるような便利機能がなかったため、この方法で取得した。
+
+※diskpartでは下記のようなデータが取れるので、その中の「Volume 0」の「0」だけ取りたかったイメージ。(図は上のサンプルと別環境なので「MYVOLUME」はない)
+![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352601/8b527a9a-fd3e-27bb-6b17-ad29a32c95db.png)
+
+
+
+# 参考
+.bat(バッチファイル)のforコマンド解説。
+https://qiita.com/sawa_tsuka/items/67be34bab1fdf3fb87f9