【問題と解答】第27回sedこわいシェル芸勉強会
Sat Feb 11 16:13:15 JST 2017 (modified: Sat Sep 30 16:15:34 JST 2017)
views: 3019, keywords:コマンド,sed,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が7年以上前のものです。
問題のみのページはこちら。
問題で使うファイル等
GitHubにあります。ファイルは
https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.27
にあります。
クローンは以下のようにお願いします。
git clone https://github.com/ryuichiueda/ShellGeiData.git $
イントロ
環境
対象とするsedはGNU sedだけに絞っています。解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールの上、gsedをつかいましょう。BSD系の人は玄人なので各自対応のこと。
Q1
次のechoの出力について、偶数番目の文字だけ大文字にしてください。できたら、奇数番目の文字だけ大文字にしてください。
echo abcdefghijklmn $
解答
###偶数番目を大文字に###
echo abcdefghijklmn | sed 's/\\(.\\)\\(.\\)/\\1\\U\\2/g'
$ aBcDeFgHiJkLmN
###奇数番目を大文字に###
echo abcdefghijklmn | sed 's/\\(.\\)\\(.\\)/\\U\\1\\L\\2/g'
$ AbCdEfGhIjKlMn
###-rを使うと多少スッキリする###
echo abcdefghijklmn | sed -r 's/(.)(.)/\\U\\1\\L\\2/g'
$ AbCdEfGhIjKlMn
Q2
seq 1 100から始めてsedだけでFizzBuzzをやってみましょう。
解答
seq 1 100 | sed '0~3s/.*/Fizz/;0~5s/$/Buzz/' |
$ sed 's/[0-9]*B/B/' | xargs
Q3
次の出力について、3行目を7行目の下に移動してください。
seq 1 10 $
解答
hで3行目をホールドスペースに突っ込み、Gでパターンスペースに戻します。
seq 1 10 | sed '3h;3d;7G' $
Q4
次のコードのmainとahoの位置を入れ替えてください。
cat aho.cc
$ #include <iostream>
using namespace std;
int main(int argc, char const* argv[])
{
aho();
return 0;
}
void aho(void)
{
cout << "aho" << endl;
}
解答
mainの部分をホールドスペースに入れる→消す→ファイルの一番後ろでホールドスペースを吐き出すという流れになります。
cat aho.cc | sed '/int/,/}/H;/int/,/}/d;$G'
$ #include <iostream>
using namespace std;
void aho(void)
{
cout << "aho" << endl;
}
int main(int argc, char const* argv[])
{
aho();
return 0;
}
###{}でまとめる###$G'
$ cat aho.cc | sed '/int/,/}/{H;d};
###もうちょっと厳密なやつ###$G'
$ cat aho.cc | sed '/ main(/,/^}/{H;d};
###そのままコンパイルして実行###$G' |
$ cat aho.cc | sed '/int/,/}/H;/int/,/}/d;
g++ -x c++ - && ./a.out aho
Q5
seq 1 10 | から始めて次のような出力を作ってください。
2
1
4
3
6
5
8
7
10
9
解答
seq 1 10 | sed '1~2h;1~2d;0~2G'
$ 2
1
4
3
6
5
8
7
10
9
Q6
echo 1から始めて次のような出力を作ってください。
1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111
解答
ラベルを使います。
echo 1 | sed ':LOOP p;s/./&&/;b LOOP' | head
$ 1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111
###分岐を使う###
echo 1 | sed ':LOOP p;s/./&&/;/1\\{10\\}/!b LOOP' $
Q7
aというファイルをtouch等で作り、次の縛りでa1, a2, a3, ..., a10というファイルをaからコピーして作ってください。縛り1と縛り2を独立した別々の問題として解き、その後縛り1,2を両方満たす解を考えてみましょう。
- 縛り1: 使うコマンドはseq、cp、sedだけ
- 縛り2: ワンライナー中で数字を使わない
解答
###縛り1###
touch a
$ seq 1 10 | sed 's/./cp a a&/e'
$ ls a a? a10
$ a a1 a10 a2 a3 a4 a5 a6 a7 a8 a9
###縛り2###
yes | sed -n '=' | head | sed 's/./cp a a&/e'
$ ###両方###
sed ':a ;p;s/./&&/;/........../!b a' <<< y |
$ sed -n = | sed 's/^/cp a a/e'
###(おまけ)ファイルaをsedで作る###
sed 'w a' <<< "abc"
$ abc
cat a
$ abc
Q8
echo 1 | から始めて、あとはsedだけで次のような出力を得てください。
1
11
111
1111
11111
11111
1111
111
11
1
解答
echo 1 | sed ':LOOP p;s/./&&/;/1\\{5\\}/!b LOOP' | sed 'p;1!G;h;$!d'
$ 1
11
111
1111
11111
11111
1111
111
11
1