2016年12月25日、一応世間ではクリスマスなのだが新宿でシェル芸勉強会があったので行ってきた。 で、その復習。
今回はエクシェル芸…というより、Excelに限らずMSオフィスのファイルをbash上でいろいろといじるという内容。 問題及び模範解答はこちら。 最初に、問題に利用するファイルをgitで落としておくといいだろう。
git clone https://github.com/ryuichiueda/ShellGeiData.git
Q1.
.xlsxや.docx、.pptxはzipファイルになっており、xlsなどのようにバイナリ形式のデータにはなっていない。 このため、unzipで展開してから再度zip化してやることで、また開けることを確認しようという問題。 問題というか、ファイルの構造を理解するのが主となっている。
とりあえず、xlsxファイルについて展開してみよう。
大体こんな感じの構造になっている。 ファイル名から、どのファイルがSheetに当たるのかは推測が立つだろう。 Excelの各シートはxmlで定義されているという事がわかる。
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od hanshin hanshin.xlsx
Archive: hanshin.xlsx
inflating: hanshin/[Content_Types].xml
inflating: hanshin/_rels/.rels
inflating: hanshin/xl/_rels/workbook.xml.rels
inflating: hanshin/xl/workbook.xml
inflating: hanshin/xl/sharedStrings.xml
inflating: hanshin/xl/theme/theme1.xml
inflating: hanshin/xl/styles.xml
inflating: hanshin/xl/worksheets/sheet1.xml
extracting: hanshin/docProps/thumbnail.jpeg
inflating: hanshin/docProps/core.xml
inflating: hanshin/docProps/app.xml
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree hanshin
hanshin
├── [Content_Types].xml
├── _rels
├── docProps
│ ├── app.xml
│ ├── core.xml
│ └── thumbnail.jpeg
└── xl
├── _rels
│ └── workbook.xml.rels
├── sharedStrings.xml
├── styles.xml
├── theme
│ └── theme1.xml
├── workbook.xml
└── worksheets
└── sheet1.xml
6 directories, 10 files
同様に、docx・pptxファイルについても展開してみる。
20141019OSC_LT.pptx certificate.docx graph.xlsx hanshin/ hanshin.xlsx template.pptx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od certificate{,.docx}
Archive: certificate.docx
inflating: certificate/[Content_Types].xml
inflating: certificate/_rels/.rels
inflating: certificate/word/_rels/document.xml.rels
inflating: certificate/word/document.xml
inflating: certificate/word/footnotes.xml
inflating: certificate/word/endnotes.xml
inflating: certificate/word/header1.xml
inflating: certificate/word/_rels/header1.xml.rels
inflating: certificate/word/theme/theme1.xml
extracting: certificate/docProps/thumbnail.jpeg
extracting: certificate/word/media/image1.png
inflating: certificate/word/_rels/settings.xml.rels
inflating: certificate/word/settings.xml
inflating: certificate/word/stylesWithEffects.xml
inflating: certificate/word/webSettings.xml
inflating: certificate/word/styles.xml
inflating: certificate/docProps/app.xml
inflating: certificate/docProps/core.xml
inflating: certificate/word/fontTable.xml
inflating: certificate/docProps/custom.xml
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree certificate
certificate
├── [Content_Types].xml
├── _rels
├── docProps
│ ├── app.xml
│ ├── core.xml
│ ├── custom.xml
│ └── thumbnail.jpeg
└── word
├── _rels
│ ├── document.xml.rels
│ ├── header1.xml.rels
│ └── settings.xml.rels
├── document.xml
├── endnotes.xml
├── fontTable.xml
├── footnotes.xml
├── header1.xml
├── media
│ └── image1.png
├── settings.xml
├── styles.xml
├── stylesWithEffects.xml
├── theme
│ └── theme1.xml
└── webSettings.xml
6 directories, 19 files
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od 20141019OSC_LT{,.pptx}
Archive: 20141019OSC_LT.pptx
inflating: 20141019OSC_LT/[Content_Types].xml
inflating: 20141019OSC_LT/_rels/.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide10.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide11.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide12.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide14.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide9.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide15.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide16.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide13.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide8.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide7.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide1.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide2.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide3.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide4.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide5.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide6.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide17.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide18.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide19.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide29.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide30.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide31.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide32.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide33.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide34.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide28.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide27.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide26.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide20.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide21.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide22.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide23.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide24.xml.rels
inflating: 20141019OSC_LT/ppt/slides/_rels/slide25.xml.rels
inflating: 20141019OSC_LT/ppt/_rels/presentation.xml.rels
inflating: 20141019OSC_LT/ppt/presentation.xml
inflating: 20141019OSC_LT/ppt/slides/slide25.xml
inflating: 20141019OSC_LT/ppt/slides/slide21.xml
inflating: 20141019OSC_LT/ppt/slides/slide20.xml
inflating: 20141019OSC_LT/ppt/slides/slide19.xml
inflating: 20141019OSC_LT/ppt/slides/slide18.xml
inflating: 20141019OSC_LT/ppt/slides/slide17.xml
inflating: 20141019OSC_LT/ppt/slides/slide16.xml
inflating: 20141019OSC_LT/ppt/slides/slide15.xml
inflating: 20141019OSC_LT/ppt/slides/slide14.xml
inflating: 20141019OSC_LT/ppt/slides/slide13.xml
inflating: 20141019OSC_LT/ppt/slides/slide22.xml
inflating: 20141019OSC_LT/ppt/slides/slide23.xml
inflating: 20141019OSC_LT/ppt/slides/slide34.xml
inflating: 20141019OSC_LT/ppt/slides/slide26.xml
inflating: 20141019OSC_LT/ppt/slides/slide27.xml
inflating: 20141019OSC_LT/ppt/slides/slide28.xml
inflating: 20141019OSC_LT/ppt/slides/slide29.xml
inflating: 20141019OSC_LT/ppt/slides/slide30.xml
inflating: 20141019OSC_LT/ppt/slides/slide31.xml
inflating: 20141019OSC_LT/ppt/slides/slide32.xml
inflating: 20141019OSC_LT/ppt/slides/slide33.xml
inflating: 20141019OSC_LT/ppt/slides/slide12.xml
inflating: 20141019OSC_LT/ppt/slides/slide11.xml
inflating: 20141019OSC_LT/ppt/slides/slide10.xml
inflating: 20141019OSC_LT/ppt/slides/slide1.xml
inflating: 20141019OSC_LT/ppt/slides/slide2.xml
inflating: 20141019OSC_LT/ppt/slides/slide3.xml
inflating: 20141019OSC_LT/ppt/slides/slide4.xml
inflating: 20141019OSC_LT/ppt/slides/slide24.xml
inflating: 20141019OSC_LT/ppt/slides/slide6.xml
inflating: 20141019OSC_LT/ppt/slides/slide9.xml
inflating: 20141019OSC_LT/ppt/slides/slide5.xml
inflating: 20141019OSC_LT/ppt/slides/slide7.xml
inflating: 20141019OSC_LT/ppt/slides/slide8.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout2.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout9.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout10.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout11.xml.rels
inflating: 20141019OSC_LT/ppt/notesSlides/_rels/notesSlide1.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout8.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout7.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout6.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout5.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout4.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout3.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/_rels/slideLayout1.xml.rels
inflating: 20141019OSC_LT/ppt/slideMasters/slideMaster1.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout1.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout8.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout9.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout10.xml
inflating: 20141019OSC_LT/ppt/slideMasters/_rels/slideMaster1.xml.rels
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout7.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout6.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout5.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout4.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout3.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout2.xml
inflating: 20141019OSC_LT/ppt/notesSlides/notesSlide1.xml
inflating: 20141019OSC_LT/ppt/slideLayouts/slideLayout11.xml
extracting: 20141019OSC_LT/ppt/media/image2.gif
inflating: 20141019OSC_LT/ppt/handoutMasters/_rels/handoutMaster1.xml.rels
extracting: 20141019OSC_LT/ppt/media/image3.png
extracting: 20141019OSC_LT/ppt/media/image10.jpg
extracting: 20141019OSC_LT/docProps/thumbnail.jpeg
inflating: 20141019OSC_LT/ppt/handoutMasters/handoutMaster1.xml
inflating: 20141019OSC_LT/ppt/notesMasters/notesMaster1.xml
inflating: 20141019OSC_LT/ppt/theme/theme1.xml
inflating: 20141019OSC_LT/ppt/notesMasters/_rels/notesMaster1.xml.rels
extracting: 20141019OSC_LT/ppt/media/image9.jpg
extracting: 20141019OSC_LT/ppt/media/image7.png
extracting: 20141019OSC_LT/ppt/media/image1.png
extracting: 20141019OSC_LT/ppt/media/image4.png
extracting: 20141019OSC_LT/ppt/media/image8.jpg
inflating: 20141019OSC_LT/ppt/theme/theme3.xml
inflating: 20141019OSC_LT/ppt/theme/theme2.xml
extracting: 20141019OSC_LT/ppt/media/image5.png
extracting: 20141019OSC_LT/ppt/media/image6.gif
inflating: 20141019OSC_LT/ppt/viewProps.xml
inflating: 20141019OSC_LT/ppt/tableStyles.xml
inflating: 20141019OSC_LT/ppt/presProps.xml
inflating: 20141019OSC_LT/docProps/app.xml
inflating: 20141019OSC_LT/docProps/core.xml
inflating: 20141019OSC_LT/ppt/printerSettings/printerSettings1.bin
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ tree 20141019OSC_LT
20141019OSC_LT
├── [Content_Types].xml
├── _rels
├── docProps
│ ├── app.xml
│ ├── core.xml
│ └── thumbnail.jpeg
└── ppt
├── _rels
│ └── presentation.xml.rels
├── handoutMasters
│ ├── _rels
│ │ └── handoutMaster1.xml.rels
│ └── handoutMaster1.xml
├── media
│ ├── image1.png
│ ├── image10.jpg
│ ├── image2.gif
│ ├── image3.png
│ ├── image4.png
│ ├── image5.png
│ ├── image6.gif
│ ├── image7.png
│ ├── image8.jpg
│ └── image9.jpg
├── notesMasters
│ ├── _rels
│ │ └── notesMaster1.xml.rels
│ └── notesMaster1.xml
├── notesSlides
│ ├── _rels
│ │ └── notesSlide1.xml.rels
│ └── notesSlide1.xml
├── presProps.xml
├── presentation.xml
├── printerSettings
│ └── printerSettings1.bin
├── slideLayouts
│ ├── _rels
│ │ ├── slideLayout1.xml.rels
│ │ ├── slideLayout10.xml.rels
│ │ ├── slideLayout11.xml.rels
│ │ ├── slideLayout2.xml.rels
│ │ ├── slideLayout3.xml.rels
│ │ ├── slideLayout4.xml.rels
│ │ ├── slideLayout5.xml.rels
│ │ ├── slideLayout6.xml.rels
│ │ ├── slideLayout7.xml.rels
│ │ ├── slideLayout8.xml.rels
│ │ └── slideLayout9.xml.rels
│ ├── slideLayout1.xml
│ ├── slideLayout10.xml
│ ├── slideLayout11.xml
│ ├── slideLayout2.xml
│ ├── slideLayout3.xml
│ ├── slideLayout4.xml
│ ├── slideLayout5.xml
│ ├── slideLayout6.xml
│ ├── slideLayout7.xml
│ ├── slideLayout8.xml
│ └── slideLayout9.xml
├── slideMasters
│ ├── _rels
│ │ └── slideMaster1.xml.rels
│ └── slideMaster1.xml
├── slides
│ ├── _rels
│ │ ├── slide1.xml.rels
│ │ ├── slide10.xml.rels
│ │ ├── slide11.xml.rels
│ │ ├── slide12.xml.rels
│ │ ├── slide13.xml.rels
│ │ ├── slide14.xml.rels
│ │ ├── slide15.xml.rels
│ │ ├── slide16.xml.rels
│ │ ├── slide17.xml.rels
│ │ ├── slide18.xml.rels
│ │ ├── slide19.xml.rels
│ │ ├── slide2.xml.rels
│ │ ├── slide20.xml.rels
│ │ ├── slide21.xml.rels
│ │ ├── slide22.xml.rels
│ │ ├── slide23.xml.rels
│ │ ├── slide24.xml.rels
│ │ ├── slide25.xml.rels
│ │ ├── slide26.xml.rels
│ │ ├── slide27.xml.rels
│ │ ├── slide28.xml.rels
│ │ ├── slide29.xml.rels
│ │ ├── slide3.xml.rels
│ │ ├── slide30.xml.rels
│ │ ├── slide31.xml.rels
│ │ ├── slide32.xml.rels
│ │ ├── slide33.xml.rels
│ │ ├── slide34.xml.rels
│ │ ├── slide4.xml.rels
│ │ ├── slide5.xml.rels
│ │ ├── slide6.xml.rels
│ │ ├── slide7.xml.rels
│ │ ├── slide8.xml.rels
│ │ └── slide9.xml.rels
│ ├── slide1.xml
│ ├── slide10.xml
│ ├── slide11.xml
│ ├── slide12.xml
│ ├── slide13.xml
│ ├── slide14.xml
│ ├── slide15.xml
│ ├── slide16.xml
│ ├── slide17.xml
│ ├── slide18.xml
│ ├── slide19.xml
│ ├── slide2.xml
│ ├── slide20.xml
│ ├── slide21.xml
│ ├── slide22.xml
│ ├── slide23.xml
│ ├── slide24.xml
│ ├── slide25.xml
│ ├── slide26.xml
│ ├── slide27.xml
│ ├── slide28.xml
│ ├── slide29.xml
│ ├── slide3.xml
│ ├── slide30.xml
│ ├── slide31.xml
│ ├── slide32.xml
│ ├── slide33.xml
│ ├── slide34.xml
│ ├── slide4.xml
│ ├── slide5.xml
│ ├── slide6.xml
│ ├── slide7.xml
│ ├── slide8.xml
│ └── slide9.xml
├── tableStyles.xml
├── theme
│ ├── theme1.xml
│ ├── theme2.xml
│ └── theme3.xml
└── viewProps.xml
19 directories, 121 files
あとは、またzip化して開けることを確認してやれば良い。 この一連の処理をワンラインで記述する場合、以下のようになる。
ls -1 *x | awk -F. '{cmd="unzip -d "$1" "$0 ";(cd "$1";zip -r ../"$1"_2."$2" ./)";system(cmd)}'
Q2.
「20141019OSC_LT.pptx」ファイルで、何度「危険」というキーワードが出てくるかを計算する。 とりあえず、以下の内容で回答した。
Q2こうか
unzip -p 20141019OSC_LT.pptx ppt/slides/slide*.xml | grep -o 危険 | wc -l
17
#シェル芸— Blacknon(エビス) (@blacknon_) 2016年12月25日
unzip -p 20141019OSC_LT.pptx ppt/slides/slide*.xml | grep -o 危険 | wc -l
一応補足説明を入れておくと、unzipでは以下のようにzipファイル内で展開するファイルを指定することができる(ワイルドカード指定可能。 (複数指定できるので)ブレース展開での指定可能)
で、PowerPointの各スライドの内容だけを取得することが目的なので「ppt/slides/」配下にあるslideXX.xmlファイルのみを取得している。 また「-p」オプションで展開した内容を標準出力で出力できるので、それをそのままgrepに渡してやり数を数えている。 このとき、-cでカウントすると同じ行に複数目当ての単語がある場合1個としてカウントされてしまうので注意。
ちなみに、unzipでは「-l」でzipファイルの中身を確認できるので、先にそれで展開するファイルの推測を立てるといいだろう。
unzip -l zipファイル
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -l certificate.docx
Archive: certificate.docx
Length Date Time Name
--------- ---------- ----- ----
2041 1980-01-01 00:00 [Content_Types].xml
882 1980-01-01 00:00 _rels/.rels
1345 1980-01-01 00:00 word/_rels/document.xml.rels
43370 1980-01-01 00:00 word/document.xml
1635 1980-01-01 00:00 word/footnotes.xml
1629 1980-01-01 00:00 word/endnotes.xml
4729 1980-01-01 00:00 word/header1.xml
289 1980-01-01 00:00 word/_rels/header1.xml.rels
7643 1980-01-01 00:00 word/theme/theme1.xml
45844 1980-01-01 00:00 docProps/thumbnail.jpeg
149691 1980-01-01 00:00 word/media/image1.png
460 1980-01-01 00:00 word/_rels/settings.xml.rels
3811 1980-01-01 00:00 word/settings.xml
9472 1980-01-01 00:00 word/stylesWithEffects.xml
431 1980-01-01 00:00 word/webSettings.xml
8606 1980-01-01 00:00 word/styles.xml
1043 1980-01-01 00:00 docProps/app.xml
754 1980-01-01 00:00 docProps/core.xml
1742 1980-01-01 00:00 word/fontTable.xml
353 1980-01-01 00:00 docProps/custom.xml
--------- -------
285770 20 files
Q3.
「20141019OSC_LT.pptx」ファイルにある画像ファイルのみを抽出し別ディレクトリに移動、zip化してやろうという問題。 以下の内容で回答している。
Q3
unzip -d ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip https://t.co/ptrhJ94tGh ./pic
拡張子、これで全部かな?— Blacknon(エビス) (@blacknon_) 2016年12月25日
unzip -d ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip -r pic.zip ./pic
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -od ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip -r pic.zip ./pic
Archive: 20141019OSC_LT.pptx
extracting: ./pic/ppt/media/image2.gif
extracting: ./pic/ppt/media/image3.png
extracting: ./pic/ppt/media/image10.jpg
extracting: ./pic/docProps/thumbnail.jpeg
extracting: ./pic/ppt/media/image9.jpg
extracting: ./pic/ppt/media/image7.png
extracting: ./pic/ppt/media/image1.png
extracting: ./pic/ppt/media/image4.png
extracting: ./pic/ppt/media/image8.jpg
extracting: ./pic/ppt/media/image5.png
extracting: ./pic/ppt/media/image6.gif
updating: pic/ (stored 0%)
updating: pic/docProps/ (stored 0%)
updating: pic/docProps/thumbnail.jpeg (deflated 22%)
updating: pic/ppt/ (stored 0%)
updating: pic/ppt/media/ (stored 0%)
updating: pic/ppt/media/image6.gif (deflated 0%)
updating: pic/ppt/media/image8.jpg (deflated 7%)
updating: pic/ppt/media/image3.png (deflated 1%)
updating: pic/ppt/media/image7.png (deflated 10%)
updating: pic/ppt/media/image2.gif (deflated 1%)
updating: pic/ppt/media/image9.jpg (deflated 12%)
updating: pic/ppt/media/image5.png (deflated 13%)
updating: pic/ppt/media/image4.png (deflated 4%)
updating: pic/ppt/media/image10.jpg (deflated 6%)
updating: pic/ppt/media/image1.png (deflated 4%)
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -l pic.zip
Archive: pic.zip
Length Date Time Name
--------- ---------- ----- ----
0 2016-12-26 12:05 pic/
0 2016-12-26 12:07 pic/docProps/
11732 1980-01-01 00:00 pic/docProps/thumbnail.jpeg
0 2016-12-26 12:05 pic/ppt/
0 2016-12-26 12:07 pic/ppt/media/
67739 1980-01-01 00:00 pic/ppt/media/image6.gif
95304 1980-01-01 00:00 pic/ppt/media/image8.jpg
13744 1980-01-01 00:00 pic/ppt/media/image3.png
159302 1980-01-01 00:00 pic/ppt/media/image7.png
99260 1980-01-01 00:00 pic/ppt/media/image2.gif
379635 1980-01-01 00:00 pic/ppt/media/image9.jpg
70496 1980-01-01 00:00 pic/ppt/media/image5.png
186174 1980-01-01 00:00 pic/ppt/media/image4.png
111613 1980-01-01 00:00 pic/ppt/media/image10.jpg
426687 1980-01-01 00:00 pic/ppt/media/image1.png
--------- -------
1621686 15 files
ただ、基本的にメディアファイルはすべて「ppt/media/」配下にあるのでそこだけ指定してやってもよかったかも。 「docProps/thumbnail.jpeg」ってサムネイルだしいらないと思われる。
Q4.
「20141019OSC_LT.pptx」のスライド7ページ目のテキストをスクレイピングする、という問題。 これについては、時間内に解くことができなかった。
で、@ebanさんの回答がやっぱりすごかったので、それ+@grethlenのQ4の回答を参考にしたのが以下。 (ほとんど丸パクリのような気もしなくも…?)
unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g' | awk NF
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # スライド7枚目の情報だけ出力する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"><p:cSld><p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr><p:sp><p:nvSpPr><p:cNvPr id="2" name="タイトル 1"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>戦果(? )</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="3" name="コンテンツ プレースホルダー 2"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph idx="1"/></p:nvPr></p:nvSpPr><p:spPr><a:xfrm><a:off x="457200" y="1599083"/><a:ext cx="8229600" cy="4708525"/></a:xfrm></p:spPr><p:txBody><a:bodyPr><a:normAutofit fontScale="92500" lnSpcReduction="10000"/></a:bodyPr><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>初日だけで見知らぬ方の</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>マシン</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0"/><a:t>3</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0"/><a:t>台轟沈</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>その他自爆者多数</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" err="1" smtClean="0"/><a:t>Docker</a:t></a:r><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>上で試したらホストマシン沈黙の報告</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>自分の本がサイト経由で</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>冊だけ売れた</a:t></a:r><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/></a:p><a:p><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0"/></a:p><a:p><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>フォロワーが</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>人減った</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="4" name="日付プレースホルダー 3"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="dt" sz="half" idx="10"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>2014/10/19</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="5" name="フッター プレースホルダー 4"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="ftr" sz="quarter" idx="11"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>OSC Tokyo/Fall 2014</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp><p:sp><p:nvSpPr><p:cNvPr id="6" name="スライド番号プレースホルダー 5"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph type="sldNum" sz="quarter" idx="12"/></p:nvPr></p:nvSpPr><p:spPr/><p:txBody><a:bodyPr/><a:lstStyle/><a:p><a:fld id="{14601655-C245-0940-ADDB-4E06ABBCA83C}" type="slidenum"><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" smtClean="0"/><a:t>7</a:t></a:fld><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/></a:p></p:txBody></p:sp></p:spTree><p:extLst><p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"><p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="3384791587"/></p:ext></p:extLst></p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr><p:timing><p:tnLst><p:par><p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot" xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main"/></p:par></p:tnLst></p:timing></p:sld>
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # grepでPerlの肯定先読み正規表現を用いて、「<a:p>~</a:p>(1行)」ごとに抽出する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)'
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>戦果(?)</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>初日だけで見知らぬ方の</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>マシン</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0"/><a:t>3</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0"/><a:t>台轟沈</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>その他自爆者多数</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" err="1" smtClean="0"/><a:t>Docker</a:t></a:r><a:r><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>上で試したらホストマシン沈黙の報告</a:t></a:r><a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>自分の本がサイト経由で</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>冊だけ売れた</a:t></a:r><a:endParaRPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/>
<a:endParaRPr kumimoji="1" lang="en-US" altLang="ja-JP" dirty="0"/>
<a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>フォロワーが</a:t></a:r><a:r><a:rPr lang="en-US" altLang="ja-JP" dirty="0" smtClean="0"/><a:t>1</a:t></a:r><a:r><a:rPr lang="ja-JP" altLang="en-US" dirty="0" smtClean="0"/><a:t>人減った</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US" dirty="0"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>2014/10/19</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
<a:r><a:rPr kumimoji="1" lang="en-US" altLang="ja-JP" smtClean="0"/><a:t>OSC Tokyo/Fall 2014</a:t></a:r><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
<a:fld id="{14601655-C245-0940-ADDB-4E06ABBCA83C}" type="slidenum"><a:rPr kumimoji="1" lang="ja-JP" altLang="en-US" smtClean="0"/><a:t>7</a:t></a:fld><a:endParaRPr kumimoji="1" lang="ja-JP" altLang="en-US"/>
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # sedでタグ関係をすべて削除する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g'
戦果(?)
初日だけで見知らぬ方のマシン3台轟沈
その他自爆者多数
Docker上で試したらホストマシン沈黙の報告
自分の本がサイト経由で1冊だけ売れた
フォロワーが1人減った
2014/10/19
OSC Tokyo/Fall 2014
7
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ # 空白行を削除する
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g' | awk NF
戦果(?)
初日だけで見知らぬ方のマシン3台轟沈
その他自爆者多数
Docker上で試したらホストマシン沈黙の報告
自分の本がサイト経由で1冊だけ売れた
フォロワーが1人減った
2014/10/19
OSC Tokyo/Fall 2014
7
Q5.
「graph.xlsx」の内容を、SSV(スペース区切り)の形式で取得するという内容。 とりあえず、最も楽なxlsx2csvで回答した。
@blacknon_
間違えた
スペースだからこっち
xlsx2csv -d ' ' graph.xlsx#シェル芸— Blacknon(エビス) (@blacknon_) 2016年12月25日
xlsx2csv -d' ' graph.xlsx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' graph.xlsx
0 -5
0.5 -7.375
1 -14
1.5 -24.125
2 -37
2.5 -51.875
3 -68
3.5 -84.625
4 -101
4.5 -116.375
5 -130
5.5 -141.125
6 -149
6.5 -152.875
7 -152
7.5 -145.625
8 -133
8.5 -113.375
9 -86
9.5 -50.125
10 -5
10.5 50.125
11 116
xlsx2csvを使わない場合は @grethlenのこちらの回答が参考になる。
Q6.
「hanshin.xlsx」について、Q5と同様にSSV形式にするという問題。 こちらも、地味にxlsx2csvを使えばいい感じにやってくれはする。
xlsx2csv -d' ' hanshin.xlsx
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' hanshin.xlsx
42522 42561
1 真弓 真弓
2 弘田 北村
3 バース バース
4 掛布 掛布
5 岡田 佐野
6 佐野 木戸
7 平田 平田
8 木戸 永尾
9 ゲイル 池田
とはいえ、それだと芸が無いので日付をUNIXTIMEに変換して加工、「YYYY年MM月DD日」形式で表示させてみる。
(ちょっと長い)
xlsx2csv -d' ' hanshin.xlsx | awk 'NR==1{for(i=1;i<NF;i++){cmd="date -d @$(echo $((("$i" - 25569) * 86400))) +%Y年%m月%d日";cmd|getline t;s=s" "t;close(cmd);}print s}NR!=1{print}'
blacknon@BS-PUB-UBUNTU-01:~/ShellGeiData/vol.26_work$ xlsx2csv -d' ' hanshin.xlsx | awk 'NR==1{for(i=1;i<NF;i++){cmd="date -d @$(echo $((("$i" - 25569) * 86400))) +%Y年%m月%d日";cmd|getline t;s=s" "t;close(cmd);}print s}NR!=1{print}'
2016年06月01日 2016年07月10日
1 真弓 真弓
2 弘田 北村
3 バース バース
4 掛布 掛布
5 岡田 佐野
6 佐野 木戸
7 平田 平田
8 木戸 永尾
9 ゲイル 池田
あとxlsx2csvを使わないで回答する方法について。 Excelでは、Stringファイルについては「xl/sharedStrings.xml」に格納されているので、ここの内容をSheetのデータである「xl/worksheets/sheet1.xml」と組み合わせてやればよい。
Excelの「xl/worksheets/sheet1.xml」から「xl/sharedStrings.xml」の値の参照は データの順番(というか、0から始まるので配列のようなイメージ。なんだそりゃ…)
になっている。
xlsx2csvを使わない方法で解くとなると、模範解答のように2ファイルに分けて対応するのが一般的だと思う。
Q7&Q8
Q7とQ8はほぼほぼセットになっている。 Wordの特定の文字列を置換して、list.txtにある3名分の表彰状を作成するというもの。 (Wordの場合、確か差し込み印刷ってなかったっけ…?とも思ったが、印刷じゃないので気にしない)
とりあえず、以下の内容で回答した。
Q8
cat list.txt|xargs -n 1 -I@ sh -c 'unzip -d @ certificate.docx;sed -i s/WINNER/@/g @/word/document.xml;(cd @;zip -r ../@.docx ./)'
#シェル芸— Blacknon(エビス) (@blacknon_) 2016年12月25日
cat list.txt | xargs -n 1 -I@ sh -c 'unzip -d @ certificate.docx;sed -i s/WINNER/@/g @/word/document.xml;(cd @;zip -r ../@.docx ./)'
これで、「シェル芸おじさん.docx」などのファイルができているはずだ。 作業用のディレクトリ削除については行ってないので、ホントだったら消しといたほうがいいかも?
Perlの肯定正規表現については知らなかったので、あとで調べておきたい。