とある駅の券売機スペース。
かつては10台以上券売機が置かれていたのが
今は7台になっていて、さらにそのうちの3台が
PASMO(SUICA)のチャージ専用機。
何のかんの言ってかわってんだねえ。
sedの話のつづき。
OS X のあれこれが BSD 由来ということで、
FreeBSD の sed を眺めてみる。
/*-
* Copyright (c) 2013 Johann 'Myrkraverk' Oskarsson.
* Copyright (c) 1992 Diomidis Spinellis.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Diomidis Spinellis of Imperial College, University of London.
*
(略)
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif
#ifndef lint
static const char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/3/94";
#endif
これね。
で、そのオプション解析部分。
int
main(int argc, char *argv[])
{
int c, fflag;
char *temp_arg;
(void) setlocale(LC_ALL, "");
fflag = 0;
inplace = NULL;
while ((c = getopt(argc, argv, "EI:ae:f:i:lnr")) != -1) ←☆☆
switch (c) {
case 'r': /* Gnu sed compat */
case 'E':
rflags = REG_EXTENDED;
break;
case 'I':
inplace = optarg;
ispan = 1; /* span across input files */
break;
case 'a':
aflag = 1;
break;
case 'e':
eflag = 1;
if ((temp_arg = malloc(strlen(optarg) + 2)) == NULL)
err(1, "malloc");
strcpy(temp_arg, optarg);
strcat(temp_arg, "\n");
add_compunit(CU_STRING, temp_arg);
break;
case 'f':
fflag = 1;
add_compunit(CU_FILE, optarg);
break;
case 'i':
inplace = optarg; ←☆☆☆
ispan = 0; /* don't span across input files */
break;
case 'l':
if(setlinebuf(stdout) != 0)
warnx("setlinebuf() failed");
break;
case 'n':
nflag = 1;
break;
default:
case '?':
usage();
}
argc -= optind;
argv += optind;
getopt に渡しているオプション文字列は "EI:ae:f:i:lnr"
なので、-i はオプションに対する引数をとり、それは省略することはできない。
実際 case 'i':
のところでも
GNU のとは違って問答無用で inplace = optarg;
としている。
再度、GNU sed の同様の部分を見ると
int
main(argc, argv)
int argc;
char **argv;
{
#ifdef REG_PERL
#define SHORTOPTS "bsnrRuEe:f:l:i::V:"
#else
#define SHORTOPTS "bsnruEe:f:l:i::V:" ←☆☆
#endif
static struct option longopts[] = {
{"binary", 0, NULL, 'b'},
{"regexp-extended", 0, NULL, 'r'},
#ifdef REG_PERL
{"regexp-perl", 0, NULL, 'R'},
#endif
{"expression", 1, NULL, 'e'},
{"file", 1, NULL, 'f'},
{"in-place", 2, NULL, 'i'}, ←☆☆☆
{"line-length", 1, NULL, 'l'},
{"quiet", 0, NULL, 'n'},
{"posix", 0, NULL, 'p'},
{"silent", 0, NULL, 'n'},
{"separate", 0, NULL, 's'},
{"unbuffered", 0, NULL, 'u'},
{"version", 0, NULL, 'v'},
{"help", 0, NULL, 'h'},
#ifdef ENABLE_FOLLOW_SYMLINKS
{"follow-symlinks", 0, NULL, 'F'},
#endif
{NULL, 0, NULL, 0}
};
(略)
while ((opt = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != EOF)
{
switch (opt)
{
SHORTOPTS の実体に含まれる 'i' には ':' が二つ続いているので
オプションに対する引数は「省略可能」。
longopts の "in-place" の行にある 2 も同じ指示をロングオプションに行うもの。
case 'i':
separate_files = true;
if (optarg == NULL)
/* use no backups */
in_place_extension = ck_strdup ("*");
else if (strchr(optarg, '*') != NULL)
in_place_extension = ck_strdup(optarg);
else
{
in_place_extension = MALLOC (strlen(optarg) + 2, char);
in_place_extension[0] = '*';
strcpy (in_place_extension + 1, optarg);
}
break;
optarg == NULL
ってのが
オプションに引数が渡されたかどうかの判定。
前回のおまけのおまけ
$ cat >argchk.sh
echo $1
echo $2
echo $3
$ bash argchk.sh aaa '' ccc
aaa
ccc
$ bash argchk.sh aaa'' ccc
aaa
ccc
$ bash argchk.sh aaa''ccc ddd
aaaccc
ddd
$ bash argchk.sh aaa' 'ccc ddd
aaa ccc
ddd
まあこうなってるわけですよ。