【問題と解答】第24回◯◯o◯裏番組シェル芸勉強会
Sat Aug 27 17:29:16 JST 2016 (modified: Sun Oct 1 10:50:27 JST 2017)
views: 3319, keywords:コマンド,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が7年以上前のものです。
問題のみのページはこちら
イントロ
問題で使うファイル等
GitHubにあります。ファイルは
https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.24
にあります。
クローンは以下のようにお願いします。
git clone https://github.com/ryuichiueda/ShellGeiData.git $
環境
今回はUbuntu Linux 16.04で解答例を作りました。
Q1
cat Q1
$
玉子 卵 玉子 玉子 玉子 玉子
玉子 玉子 卵 卵 卵 玉子
卵 玉子 卵 玉子 玉子 玉子
卵 玉子 卵 卵 卵 卵 玉子 卵 玉子
上のようなQ1ファイルについて、次のような出力を得てください。
5 卵:1
玉子:3 卵:3
玉子:4 卵:2
玉子:1 卵:5
玉子:2 卵:1 玉子:
解答
AWKの力技になります。力技でない方法を募集。
cat Q1 |
$ awk '{for(i=1;i<=NF;i++){a[$i]++};for(k in a){printf("%s:%d ",k,a[k]);a[k]=0}print ""}'
5 卵:1
玉子:3 卵:3
玉子:4 卵:2
玉子:1 卵:5
玉子:2 卵:1 玉子:
Q2
次のようなテキストについて、繰り返し出てきた文字の2つ目以降を省いて出力してください。例えばQ2のファイル
cat Q2
$ へのへのもへじ
の場合、「へのもじ」が正解の出力になります。
解答
cat Q2 | grep -o . | nl | sort -k2,2 -k1,1n |
$ uniq -f 1 | sort | awk '{printf $2}' | xargs
へのもじcat Q2 | grep -o . | awk '{if(!a[$1]){printf $1};a[$1]=1}END{print ""}'
$
へのもじ< Q2 grep -o . | awk '{if(!a[$1]){printf $1};a[$1]=1}' | xargs
$ へのもじ
Q3
cat Q3
$
金 日成
キム ワイプ
金 正日
キム タオル 金 正男
というデータを、
%%
キム タオル
キム ワイプ%%
金 正男
金 正日
金 日成%%
というように第一フィールドをキーにして%%でレコードを区切ってください。awkを使ってできた人は、awkを使わないでやってみてください。
解答
sort Q3 | awk '{if($1!=a){print "%%";print;a=$1}else{print}}END{print "%%"}'
$ %%
キム タオル
キム ワイプ%%
金 正男
金 正日
金 日成%%
sort Q2 | rev | uniq --group=both -f 1 | rev | sed 's/^$/%%/'
$ %%
キム タオル
キム ワイプ%%
金 正男
金 正日
金 日成%%
Q4
Q4.xlsxのA1のセルには数字が書いてあります。その数字を出力してください。A4には文字列が書いてあるので余裕がある人はそれも特定してみましょう。
解答
A1のセル(数字の読み方)
unzip -p Q4.xlsx xl/worksheets/sheet1.xml | sed 's;</c>;&\\n;g' |
$ grep -o '<c.*</c>' | grep A1 | sed 's;.*<v>;;' | sed 's;<.*;;'
114514
unzip -p Q4.xlsx xl/worksheets/sheet1.xml | hxselect -s '\\n' c |
$ grep A1 | hxselect -c v
114514
A2の文字列の読み方。シートには文字列のIDが書いてあるのでこれで文字列のシートを読んで特定。
###これで6番目(0番から始まるので7番目)の文字列とわかる###
unzip -p Q4.xlsx xl/worksheets/sheet1.xml |
$ hxselect -s '\\n' c | grep A4
<c r="A4" t="s"><v>6</v></c>
###抽出###
unzip -p Q4.xlsx xl/sharedStrings.xml |
$ hxselect -s '\\n' si | awk 'NR==7'
<si><t>エクシェル芸</t><rPh sb="5" eb="6"><t>ゲ</t></rPh><phoneticPr fontId="1"/></si>
Q5
ファイルQ5について、xに好きな数を代入して各行の式を計算してください。
cat Q5
$ x + x^2
x + 1/x
x*x*x
余裕のある人は、例えばxに2を代入したければ、
echo 2 | ... $
というようにecho <代入したい数>から始めてワンライナーで解いてみてください。
解答
例えばこれで解けます。(-2)のカッコはQ5ファイルでは不要なようです。
sed 's/x/(-2)/g' Q5 | bc -l
$ 2
-2.50000000000000000000
-8
echo <数字>からスタートすると、ややこしくなります。
echo -2 | xargs -I@ awk -v a=@ '{gsub(/x/,a,$0);print}' Q5 | bc -l
$ 2
-2.50000000000000000000
-8
Q6
「玉子」と「卵」の数を数えて、数が少ない方を数が大きい方で置換してください。
cat Q6
$ 卵卵玉子玉子玉子玉子玉子卵卵卵玉子玉子卵玉子玉子玉子玉子卵卵玉子卵玉子卵卵玉子卵玉子
解答
力技です。
cat Q6 | grep -oE '(玉子|卵)' | sort | uniq -c |
$ sort -n -k1,1n | awk '{print $2}' | xargs |
awk '{print "s/"$1"/"$2"/g"}' | xargs -I@ sed @ Q6
玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子
Q7
次のseq(あるいはjot等)の出力から、各桁の数字の構成が同じもの(例: 11122と22111等)を重複とみなし、除去してください。
seq -w 00000 99999 $
解答
###asortを使う場合###
seq -w 00000 99999 | sed 's/./& /g' |
$ awk '{for(i=1;i<=NF;i++)a[i]=$i;asort(a);for(k in a){printf a[k]}print ""}' |
sort -u
###ちょっと気の利いた方法(数字が小さい順に並んでいるものだけ残す)###
seq -w 00000 99999 | sed 's/./& /g' |
$ awk '$1<=$2&&$2<=$3&&$3<=$4&&$4<=$5' | tr -d ' '
Q8
まず、1〜7を全て含む7桁の整数を全て列挙して、tmpというファイルに出力してください。
次に、相異なる7以下の正の整数a,b,c,d,e,f,gを用いて、
abcd + efg
と表せる素数と、その時のa〜gの数字を全て求めましょう。tmpを用いて構いません。
(参考: 2011年日本数学オリンピック予選第3問から。一部改。http://www.imojp.org/challenge/old/jmo21yq.html)
解答
1は力技になります。
seq -w 0000000 9999999 | grep -v [089] |
$ grep 1 | grep 2 | grep 3 | grep 4 | grep 5 | grep 6 | grep 7 > tmp
2は、うまくwhileとfactorを使って求めます。
cat tmp | sed 's/./& /g' | awk '{print $1$2$3$4$5$6$7,$1*$2*$3*$4+$5*$6*$7}' | while read a b ; do echo $b | factor | awk -v n=$a 'NF==2{gsub(/./,"& ",n);print n,$2}' ; done
$ 2 3 4 6 1 5 7 179
2 3 4 6 1 7 5 179
2 3 4 6 5 1 7 179
2 3 4 6 5 7 1 179
2 3 4 6 7 1 5 179
2 3 4 6 7 5 1 179
2 3 6 4 1 5 7 179
2 3 6 4 1 7 5 179
2 3 6 4 5 1 7 179
...