シス管系女子BEGINS 第0.2話

シス管系女子をシェア!

このエントリーをはてなブックマークに追加

16コマ目

(16コマ目)
ええっ?!
cdコマンドを実行したのに移動しないなんてことがあるんですか!?

ピリオド(ドット)2個の「..」と1つだけの「.」は、ファイル名やディレクトリー名として書くと特別な意味になるの

解説

大野先輩のこのポーズ(手のひらを差し出す)は、人差し指を立てるポーズの次に頻出な気がします。

そして、sakuraさんの15日目のご参加ありがとうございます! せっかくなので自分もこの課題に挑戦してみました。awkは分からないので(ひどい)、けっこう力業です。

#!/bin/bash

# 冒頭の説明文を保持しておく。
description=''
while read line
do
  # 空行が表れたら説明文の終わり。
  [ "$line" = '' ] && break
  description="$description$(echo "$line")"
done

# レコード部分格納用の一時ファイルを作成する。
# (一時ファイルを使うのは、その方が楽だから)
records_path=$(mktemp)
# 各フィールドを保持する変数を初期化する。
title=''
metadata=''
url=''

# 後でソート等の処理をしやすいように、
# 複行レコードを一行レコードに変換する。
# sed: フィールドの区切りにのみスペースが表れるようにするために、
#      「%」をエスケープした上でスペースもエスケープしておく。
#      ここでまとめてやっておくと、1レコードごとにsedするより
#      効率が良い(はず)。
sed -e 's/%/%25/g' -e 's/ /%20/g' |
  while read line
do
  if [ "$line" = '' ] # 空行が表れたらレコードの終わり。
  then
    # titleが空でなければレコードの情報があるので出力。
    if [ "$title" != '' ]
    then
      # echo: 後処理のことを考えて、各フィールドを
      #       スペース区切りで、且つ逆順にして出力する。
      # >>:   変換結果を1レコードとして一時ファイルに
      #       追記する。
      echo "$url $metadata $title" \
        >> "$records_path"
    fi
    # 各フィールドの値を空に戻す
    title=''
    metadata=''
    url=''
  elif echo "$line" | egrep '^https?:' 2>&1 >/dev/null
  then
    # http:またはhttps:で始まる行はURLとみなす。
    url="$line"
  elif [ "$title" = '' ]
  then
    # titleが空なら、最初のフィールドなので
    # それはタイトルとみなす。
    title="$line"
  else
    # タイトルの後に現れたフィールドでURLではない物は
    # カテゴリ情報とみなす。
    metadata="$line"
  fi
done

# ここからは出力部。

# まず説明文を出力。
echo "$description"
echo ''

# レコード部分を出力
# sort:  3番目のフィールド(タイトル)昇順
#        →2番目のフィールド(カテゴリ)降順
#        →1番目のフィールド(URL)降順
#        とソートする。
# uniq:  2番目までのフィールドをスキップして、
#        3番目のフィールド(=タイトル)が重複している
#        物を削除。
# while: 以上の結果を1レコードずつ取り出して処理する。
cat "$records_path" |
  sort -k 3,3 -k 2,2r -k 1,1r |
  uniq -f 2 |
  while read line
do
  # tr:   フィールドの区切りを改行に戻し、
  # grep: 空行を削除して(「.」にマッチする=何かある行)
  # tac:  逆順に並べ替えて、
  #       (これで、タイトル→カテゴリ→URL の順に戻る)
  # sed:  エスケープした文字を元にす。
  echo "$line" |
    tr ' ' '\n' |
    grep '.' |
    tac |
    sed -e 's/%20/ /g' -e 's/%25/%/g'
  # レコード区切りの空行を出力。
  echo ''
done

# 一時ファイルを削除
rm -rf "$records_path"

説明のためのコメントを入れたり読みやすさのためにマメに改行したりしているので縦に長いですが、詰めれば30行くらいのスクリプトです。

#!/bin/bash
description=''
while read line; do
  [ "$line" = '' ] && break
  description="$description$(echo "$line")"
done
records_path=$(mktemp)
title=''; metadata=''; url=''
sed -e 's/%/%25/g' -e 's/ /%20/g' | while read line; do
  if [ "$line" = '' ]; then
    [ "$title" != '' ] && echo "$url $metadata $title" >> "$records_path"
    title=''; metadata=''; url=''
  elif echo "$line" | egrep '^https?:' 2>&1 >/dev/null; then
    url="$line"
  elif [ "$title" = '' ]; then
    title="$line"
  else
    metadata="$line"
  fi
done
echo "$description"
echo ''
cat "$records_path" | sort -k 3,3 -k 2,2r -k 1,1r | uniq -f 2 | while read line; do
  echo "$line" | tr ' ' '\n' | grep '.' | tac | sed -e 's/%20/ /g' -e 's/%25/%/g'
  echo ''
done
rm -rf "$records_path"

これを「sort_recon_list.sh」みたいな名前で保存してchmod +x sort_recon_list.shで実行権限を付けてcat recon_list | ./sort_recon_list.shとすると課題の答えが出力されると思うのですが、どうでしょうか?(要求仕様を見落としてたらすみません!)

基本戦略としては、レギュレーションに触れない範囲で、問題を解きやすい形に変換するという方針でやってみました。

「扱いにくいデータを扱いにくい形式のまま操作するよりは、レギュレーションが許す限り扱いやすい形に寄せていく」というのが、プログラミングでは一般的に言えるセオリーだと思います。ここでは「Bashスクリプトで」というレギュレーションだけ課すことにして、それ以外は自由にやってみました。もちろん、言語の縛りが無いならRubyなどの高機能な言語を使った方がきっと楽ですけどね!

前のコマへ

次のコマへ

シス管系女子 Advent Calendar 2016に戻る

他のマンガを見る

拡散希望!

このエントリーをはてなブックマークに追加