使用 Shell 花括号展开

我们先来简单看下,什么是 Shell 花括号展开,在终端输入如下内容回车:

$ echo {1..5}
1 2 3 4 5

可以看到 {1..5} 被 Shell 展开为 1 2 3 4 5,我们再来看几个例子:

$ echo person_{1..5}
person_1 person_2 person_3 person_4 person_5

$ echo hello_{1..5}_word
hello_1_word hello_2_word hello_3_word hello_4_word hello_5_word

接下来是一个带有多个 {} 的例子:

$ echo a{1..5}b{3..6}c
a1b3c a1b4c a1b5c a1b6c a2b3c a2b4c a2b5c a2b6c a3b3c a3b4c a3b5c a3b6c a4b3c a4b4c a4b5c a4b6c a5b3c a5b4c a5b5c a5b6c

Shell 会根据 {} 的个数产生其笛卡尔积个串。{} 里面不仅可以由 .. 来表示一个序列中任一个字符,也可以使用逗号表示其列表中任一个字符,看这个例子:

$ echo a{1,8,b}c
a1c a8c abc

OK, 这就是 Shell 花括号展开式的作用啦,下面我们来看一个实际应用场景。

有这样一个需求,我们需要在一张数据表里面构造一些数据,假设是一张成绩表(users),分别有语文(chinese),数学(math),英语(english),这三个字段。手动往数据库里面当然是可以做到的,但是太费时间,用 PHP 写个循环插多条记录也比较快,但是至少还是得需要十几行代码,需要连数据库啊,需要在循环体里面插记录啊。这种情况 Shell 的花括号展开就可以派上用场啦。我们先写插入一条记录的 SQL:

insert user (chinese,math,english) values (80, 90, 70);

然后这样:

$ echo "insert user (chinese,math,english) values ("{80..90}", "{70..98}", "{68,70}");"

就会输出多条插入语句,在 MySQL 里面运行一下就 OK 啦。

有空多学一下这些技巧,虽然前期需要花点时间学习,但是一旦学会使用后在以后的工作中可以节约大量时间。

最近在看《The Linux Comand Line》这本书,这是一本开源的讲 Linux 命令行的书。以前都是用到什么看下手册或者在网上搜下,没有系统的学习过,书里面的内容大部分比较清楚(本人命令还算用得比较熟练啦),这两天感觉最大的收获就是知道了 Shell 花括号展开这个神器。

storytlr 支持搜索标题和内容

storytlr 搜索很奇怪,比如我有一篇文章,标题为“QQ for Linux 新版本终于发布了”,内容为“发布了发布了等等等。。。。。很多字符哈哈哈”,我在搜索框里搜索以下内容可以搜到这篇文章:“Linux”、“QQ for Linux”、“新版本终于发布了”,但是搜索以下内容搜不到这篇文章:“Linu”、“QQ for”、“版本”、“新版本终于发布”。这就奇怪了,于是查看代码,在源文件

./protected/application/admin/models/Data.php

的 236 行可以看到,采用的搜索方式是 MATCH,并不是 LIKE,之前没见过 MATCH,于是查看 MySQL 官网,点击这里这里

Any word that is too short is ignored. The default minimum length of words that are found by full-text searches is four characters.

也就是说会省略小于等于 4 个字符的词会省略,所以搜索“QQ for” 搜索不到。

The FULLTEXT parser determines where words start and end by looking for certain delimiter characters; for example, “ ” (space), “,” (comma), and “.” (period). If words are not separated by delimiters (as in, for example, Chinese), the FULLTEXT parser cannot determine where a word begins or ends.

中文词与词之间没有像英文那样有个空格隔开,所以 “新版本终于发布” 和 “新版本终于发布了” 并没有匹配,它认为是两个不同的词。

找到问题所在了。为了满足我的要求,我改代码为使用 LIKE 进行搜索,并且,它默认只搜索标题,不搜索内容,我对 SQL 语句作了如下改动。

Data.php 文件的 234 到 242 行内容为:

$sql = "SELECT d.id, d.source_id, d.service, UNIX_TIMESTAMP(d.timestamp) as timestamp, d.is_hidden, d.user_id, d.comment_count, d.mention_count, d.tag_count, d.slug "
		. "FROM {$service}_data t LEFT JOIN data d ON (t.id = d.id AND t.source_id = d.source_id) "
		. "WHERE MATCH($index) AGAINST(:term) AND t.source_id= :source_id "
		. ((!$show_hidden) ? "AND is_hidden = 0 " : " ")
		. "ORDER BY timestamp DESC ";

$data = array(":term" => $term, ":source_id" => $source_id);

$stmt   = $this->_db->query($sql, $data);

更改为:

$sql = "SELECT d.id, d.source_id, d.service, UNIX_TIMESTAMP(d.timestamp) as timestamp, d.is_hidden, d.user_id, d.comment_count, d.mention_count, d.tag_count, d.slug "
		. "FROM {$service}_data t LEFT JOIN data d ON (t.id = d.id AND t.source_id = d.source_id) "
		. "WHERE (title LIKE '%{$term}%' "
		// 下面这行代码是为了搜索 content 字段,有些表没有 content 字段,所以先进行一个判断
		. (($service == 'rss') ? "OR content LIKE '%{$term}%' " : "")
		. ") AND t.source_id= {$source_id} "
		. ((!$show_hidden) ? "AND is_hidden = 0 " : " ")
		. "ORDER BY timestamp DESC ";
$stmt   = $this->_db->query($sql);

我无视了 search 函数的 $index 参数,直接在 SQL 语句里用 title 替代了。

暂时一切运行正常。可以正常搜索,可以搜索文章标题和内容。

对于 MATCH AGAINST ,如果我理解有误,请看官指点。如果有更好的解决方法,请告之~

storytlr 安装出现错误

出现错误:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘) ENGINE=MyISAM DEFAULT CHARSET=utf8’ at line 19

经检查出错文件是:

protected/install/database/update/003/add_mentions_table.sql

该 SQL 语句多了一个逗号,将 UNIQUE KEY `item` USING BTREE (`source_id`, `item_id`, `url`), 后的逗号去掉即可。

Foreign key constraint is incorrectly formed

朋友,如果你也遇到了这个问题,建立外键的字段必须和引用表的字段一模一样的类型,请用 show create table table_name 查看是否一致。

今天在给一个表建外键的时候出现如题所示错误。

情况是这样的。我有一个bysj_student表,结构如下:

CREATE TABLE `bysj_student` (
	`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
	`stuno` VARCHAR(20) NOT NULL,
	`name` VARCHAR(20) NOT NULL,
	`gender` VARCHAR(2) NOT NULL,
	`major_id` INT(11) UNSIGNED NOT NULL,
	`tel` VARCHAR(11) NOT NULL,
	`email` VARCHAR(50) NOT NULL,
	PRIMARY KEY (`id`)
)

还有另一个bysj_stu_sub表,结构如下:

CREATE TABLE `bysj_stu_sub` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`student_id` INT(11) NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	INDEX `student_id` (`student_id`),
	CONSTRAINT `bysj_stu_sub_ibfk_1` FOREIGN KEY (`student_id`) REFERENCES `bysj_student` (`id`)
)

bysj_stu_sub表里的student_id是bysj_student表的外键,但是在创建bysj_stu_sub表时,会提示错误:

SQL Error (1005): Can't create table 'test.bysj_stu_sub' (errno: 150)  Foreign key constraint is incorrectly formed

网上搜索之后才明白,建立外键的字段必须和引用表的字段一模一样的类型
于是将bysj_stu_sub表的student_id字段属性改为

`student_id` INT(11) UNSIGNED NULL DEFAULT NULL

再建表就没有问题了。

(原博客发布时间:2011-11-27 09:27:26)