2016年12月25日、一応世間ではクリスマスなのだが新宿でシェル芸勉強会があったので行ってきた。 で、その復習。
今回はエクシェル芸…というより、Excelに限らずMSオフィスのファイルをbash上でいろいろといじるという内容。 問題及び模範解答はこちら。 最初に、問題に利用するファイルをgitで落としておくといいだろう。
bash
git clone https://github.com/ryuichiueda/ShellGeiData.git
Q1.
.xlsxや.docx、.pptxはzipファイルになっており、xlsなどのようにバイナリ形式のデータにはなっていない。 このため、unzipで展開してから再度zip化してやることで、また開けることを確認しようという問題。 問題というか、ファイルの構造を理解するのが主となっている。
とりあえず、xlsxファイルについて展開してみよう。
大体こんな感じの構造になっている。 ファイル名から、どのファイルがSheetに当たるのかは推測が立つだろう。 Excelの各シートはxmlで定義されているという事がわかる。
shellblacknon@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ファイルについても展開してみる。
shell20141019OSC_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化して開けることを確認してやれば良い。 この一連の処理をワンラインで記述する場合、以下のようになる。
bash
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日
bashunzip -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ファイルの中身を確認できるので、先にそれで展開するファイルの推測を立てるといいだろう。
bashunzip -l zipファイル
shellblacknon@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日
bashunzip -d ./pic 20141019OSC_LT.pptx *{png,gif,jpeg,jpg};zip -r pic.zip ./pic
shellblacknon@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の回答を参考にしたのが以下。 (ほとんど丸パクリのような気もしなくも…?)
bash
unzip -p 20141019OSC_LT.pptx *slide7.xml | grep -oP '(?<=<a:p>).*?(?=</a:p>)' | sed 's/<[^>]*>//g' | awk NF
shellblacknon@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日
bash
xlsx2csv -d' ' graph.xlsx
shellblacknon@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を使えばいい感じにやってくれはする。
bash
xlsx2csv -d' ' hanshin.xlsx
shellblacknon@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日」形式で表示させてみる。
(ちょっと長い)
bash
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}'
shellblacknon@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日
bash
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の肯定正規表現については知らなかったので、あとで調べておきたい。