MySQL语句实现字段拆分成多行

问题简述

如上图,拆分字段为多行,只使用MySQL本身功能,不借助其它工具。

下页结合实例详述原理,最后是完整的拆分语句。实际使用中,只需把最后一节的语句当作模板,修改字段名、表名即可。

核心知识点

    • 表连接关系 JOIN... ON 中使用小于号,而非通常用的等号
    • MySQL函数 SUBSTRING_INDEX() 详参MariaDB文档MySQL文档

示例数据表article_tags

文章标签表,文章编号aid,及文章标签`tags` ;即待拆分tags数据,分隔符为 " | ",竖线及前后空格共计三个字符。

CREATE TABLE `article_tags` (
  `aid` int(11) NOT NULL COMMENT 'article id',
  `tags` varchar(255) NOT NULL DEFAULT '',
  KEY `aid` (`aid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

辅助表sp_idx

拆分过程需要一张辅助表,包含了正整数的序列的一列数据。可按下页语句构造1024行。

CREATE TABLE `sp_idx` (
 `id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
 `x` bit(1) NOT NULL DEFAULT b'0',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='拆分辅助表(正整数序列)';
INSERT into `sp_idx`(`id`,`x`) values(1,0);
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;
INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;

计算每条记录拆分条数

计算每行要拆分成的行数据,即有多少条数据通过分隔符拼接在一起。即计算字符串中删除分隔符后长度的减少量,即是 分隔符的个数*分隔符长度。分隔符个数+1 即是拆分条数。

这里使用char_length()计算长度;因为分隔符可能包含ASCII码,故不用length()。

SELECT r.`aid`, `tags`,
 (char_length(`tags`)-char_length(REPLACE(`tags`,' | ',''))) DIV char_length(' | ') + 1 as kw_count 
FROM `article_tags` r ;

联入入辅助表

按上步计算出的kw_count,联入相应条数的序列数据,从1 到 kw_count,序列数据从辅助表取。联表关系使用 < ,而不是通常使用的等于。

SELECT r.`aid`, `tags`
 ,x.`id`
FROM `article_tags` r INNER JOIN `sp_idx` x 
ON x.`id` <= (char_length(tags)-char_length(REPLACE(tags,' | ',''))) DIV char_length(' | ') + 1
;

按序号取子串

结果记录集最后一列id,事实上就是原始字符的排序号。每条记录按该序号截取子串即是结果了。这里使用 SUBSTRING_INDEX() 函数,截取前N段或后N段子串。

第一步,如下,截前N段子串的结果,再截最后一段即是每行所需结果。

SELECT r.`aid`, `tags`
 ,x.`id`, substring_index(`tags`,' | ',x.`id`) as step_1
 ,substring_index(substring_index(`tags`,' | ',x.`id`),' | ',-1) as step_2
FROM `article_tags` r
INNER JOIN `sp_idx` x 
on x.`id` <= (char_length(tags)-char_length(REPLACE(tags,' | ',''))) DIV char_length(' | ') + 1
;

总结整个过程

SELECT r.`aid`, `tags`
,x.`id` as idx, substring_index(substring_index(`tags`,' | ',x.`id`),' | ',-1) as piece
FROM `article_tags` r INNER JOIN `sp_idx` x 
ON x.`id` <= (char_length(`tags`)-char_length(REPLACE(`tags`,' | ',''))) DIV char_length(' | ') + 1 
WHERE r.`tags`!='' HAVING `piece` !='';

该语句,可以当作模板使用,其中:

  • `tags` 替换为待拆分字段(共4处),' | ' 为分隔字符串(共4处);
  • `piece`为拆分结果列,`idx` 为 `piece`在原始`tags`中的序号;
  • 比前面步骤增加了WHERE及HAVING子句,用来排除原表tags为空字符串的行、及拆分piece为空字符串的行。

辅助表`sp_idx`需要事先建好,事实上只要从是从1开始的整数序列即可;如果待拆分子串数超过1024,则要扩充本表,多跑几次该句即可:INSERT into `sp_idx`(`x`) SELECT `x` FROM `sp_idx`;

如果实在不方便建辅助表,可以使用`mysql`. `help_topic`表的help_topic_id字段(不推荐)。要能保证其完整性,而且最大拆分子串数不大于`help_topic`的总行数。而且还要多加个where条件 help_topic_id>0,否则会拆分出多余的空串行,因为help_topic_id字段是从0开始编号的。

附件:

示例数据及SQL脚本 split_field_to_lines_in_mysql.zip

amazon lightsail使用记录及主要配置项(CentOS 7实例)

从朋友处得知amazon的lightsail,有东京机房而且网络质量还不错,价格还公道(512M最低配3.5刀),于是想换掉已经使用了7年的linode,正在用的早已绝版的东京1也4年了,网络抽风的频率有点高。试用过一段时间的东京2,网络质量确实有待改善。好几年前试用过aws的1年免费,啥都没干而浪费掉了,那时还跟linode一样是20刀1月。

英文国际版 https://aws.amazon.com/lightsail/

中国优化版 https://amazonaws-china.com/cn/lightsail/

网上有人说lightsail中文页面价格比英文高,可能是以前吧,现在并不是,所以跟随aws的提示进优化过的中文版,而且英文版可能还要科学上网(否则页面加载不完整)。

直接购买,目前最低配的首月免费,位置选择东京,平台选Linux/Unix,蓝图选仅操作系统-CentOS ,实例计划选最低的3.5刀版本,创建即可。关于系统版本,不选用预装应用(如Wordpress, Nginx等)的版本,是希望拿到干净的系统,按自己的需要定制。其实这点全看个人喜好了。

VPS实例初始化很快,搞一个静态IP地址,关联上去,免费的。

用户登录

默认不允许用户名/密码的登录方式,使用密钥对登录,按照提示进行即可。自带的用户名是centos,也可以先使用Web版SSH连接到服务器。关于用户方案推荐如下:

  • 先用web版ssh登录,添加一个新用户,设置密码,默认用户centos不去动它,似乎lightsail管理后台要用。useradd {yourname}; passwd {yourname}
  • 如果你使用linux/cygwin/maxosx,推荐把你的ssh公钥添加上去,以便直接ssh公钥登录,这比密码更安全,注意要 chmod 600 /home/{yourname}/.ssh/authorized_keys
  • 按后台提示创建适合putty用的密钥对,保存好不要泄漏。
  • 开启密码登录(只使用ssh密钥可略过):修改/etc/ssh/sshd_config 找到其中 PasswordAuthentication no 一行,删除或改成 PasswordAuthentication yes
  • (接上条)增强ssh,不允许root用户直接登录、只允许指定用户(默认用户centos及前面新建用户)登录,/etc/ssh/sshd_config 结尾追加如下两行
    AllowUsers {yourname} centos
    PermitRootLogin no

    记得systemctl restart sshd 重启sshd

防火墙/iptables

lightsail后台防火墙默认只开了几个端口,而iptables则完全开放(添加一条规则“所有TCP+UDP” 即可),推荐防火墙全开,而开启linux的iptables。如果不能掌握iptables基础使用,还是使用后台防火墙吧。

yum install iptables-services
systemctl start iptables
systemctl enable iptables

这样 iptables -L就显示默认规则了,按需要开启端口

iptables -I INPUT 5 -m state --state NEW -p tcp --dport 80 -j ACCEPT
iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT

[tip] lightsai防火墙没有开启ping或icmp的选项,但当允许了“所有TCP+UDP” 后,就可以ping了。

SELinux

lightsail的CentOS 7默认是开启SELinux的,玩不来还是关了的好. 临时关闭setenforce 0,修改配置文件/etc/selinux/config永久关闭。

 

python pip安装ConfigParser/MySQL-python的Hack方案

python3.x下pip报错No module named 'ConfigParser'

cygwin下virtual-env的python3.6下安装 MySQL-python报错,错误消息如后,提示找不到ConfigParser模块,而事实上该模块在python3.x后改名了。那就照旧名做个包,引用进去。

文件 /path-to-you-python/site-packages/ConfigParser.py

内容如下(事实上只要第二行就行),再运行正常了。(当然mysql-python的其他依赖包之前已经安装过。)

"""compatible configparser"""
from configparser import *
$ pip install MySQL-python
Looking in indexes: https://mirrors.ustc.edu.cn/pypi/web/simple
Collecting MySQL-python
  Downloading https://mirrors.ustc.edu.cn/pypi/web/packages/a5/e9/51b544da85a36a68debe7a7091f068d802fc515a3a202652828c73453cad/MySQL-python-1.2.5.zip (108kB)
    100% |████████████████████████████████| 112kB 799kB/s
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "", line 1, in 
      File "/tmp/pip-install-pasqnywc/MySQL-python/setup.py", line 13, in 
        from setup_posix import get_config
      File "/tmp/pip-install-pasqnywc/MySQL-python/setup_posix.py", line 2, in 
        from ConfigParser import SafeConfigParser
    ModuleNotFoundError: No module named 'ConfigParser'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-pasqnywc/MySQL-python/
(py36)

python3.x下pip安装 pymysql 代替MySQL-python 的方案

MySQL-python/MySQLdb 模块实在太久没有更新了,MariaDB发布后,其devel包的文件与mysql-devel有所不同,将造成编译失败。网上有hack方案,照着做补丁编译实在太麻烦,其实完全可以使用pymysql代替。

pip install pymysql

安装pymysql

新建个文件 /path-to-you-python/site-packages/MySQLdb.py 内容如下

"""compatible MySQLdb"""
from pymysql import *
install_as_MySQLdb()

完工。

前述的错误消息示例如后。如果还没安装mysql-devel包,报错将如下:

    _mysql.c:44:10: fatal error: my_config.h: No such file or directory
     #include "my_config.h"

装过MariaDB的devel包安装会报如下编译错误:

    In file included from _mysql.c:44:0:
    /usr/include/mysql/my_config.h:3:2: warning: #warning This file should not be included by clients, include only <mysql.h> [-Wcpp]
     #warning This file should not be included by clients, include only <mysql.h>
      ^~~~~~~

 

 

dokuwiki经验总结

设置

尽量不要直接修改doku程序源码(原因:容易出错,官方发布更新后还得麻烦一次);除非你对php程序足够自信、且不怕麻烦。

fnencode

linux/unix环境下,推荐在 管理-配置管理器-高级设置  里把 fnencode 改成utf-8,这样服务器上的中文文件名也将显示为原始文件名,会方便很多。(不要像网上有些文章里说的直接修改代码)。如果已经有非ascii文件名,可以先将它们改成英文文件名,改过fnencode后再从英文文件名改回来;否则非ascii码文件在前台将全部不可见。如果media附件也有非ascii码,好像没办法改。

扩展(插件/主题)

douku的扩展有两大类,插件与主题。以下都是插件,并且都可以在dokuwiki后台在线安装。尽量不要从别处下载扩展,以免夹带不好的私货。后台扩展管理界面,

  • Move 页面改名,并能自动修正所有相关链接
  • edittable 可视化编辑表格;从excel、网页等复制表格后,可以直接在可视化编辑界面粘贴
  • IPGroup 可以把某个ip的用户直接授权为相应的用户组。doc
  • WordPress authentication  允许使用wordpres站点的用户作为doku用户。

修改git提交的历史

前言

如果是团队协合中的git仓库,其历史最好不要修改;但如果是没有别人参与的个人项目,那就随便了,自己开心就好。毕竟,历史的条理与历史的真象,在哲学上就是一对矛盾。以下所有操作前,都最好把整目录备份一下,方便出错时从头再来。

修改最近一次提交及指定提交时间

git commit --amend --date "Wed, 01 Jan 2020 15:40:30 +0800"

commit 命令的 --amend 参数这个很简单,应该都用过。主要是 --date 这个参数,用来手工指定本次提交的时间(而不是默认的上次提交时间当前前系统时间),但是,它的日期格式 GIT_COMMITTER_DATE 不是汉语日常习惯的日期格式,很不方便手写,可以通过date命令做转换,如下(注意其中的三层引号是不同的,如果不熟悉bash可以死记,从外到内分别是单、反、双):

git commit --date '`date -R -d "2020/1/1 15:40:30"`'

删除文件

假设要删除passwords.txt的文件,让在整个git历史像不存在过一样

git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

上面命令默认保留空提交,即删除文件后某些提交会成空提交,如清空这些空提交,可加入参数 --prune-empty

单个文件改名/单目录改名

git filter-branch --tree-filter 'if [ -f old-name.txt ]; then mv old-name.txt new-name.txt; fi' HEAD
git filter-branch --tree-filter 'if [ -d old-name ]; then mv old-name new-name; fi' HEAD

如上两行,分别是对单文件改名(old-name.txt  -> new-name.txt), 单目录改名(old-name -> new-name) ,事实上并没区别。

注意 .git/refs/original/refs/heads 目录要为空。否则会报错说"Cannot create a new backup. A previous backup already exists in refs/original/  Force overwriting the backup with -f",然而加-f参数似乎并没有用;可直接删除目录 .git/refs/original。  执行过该命令,就会生成一次.git/refs/original/refs/heads/master,大概是filter-branch的后悔药(备份目录)

如果有多个分支,可以强行将分支们合并,改过名后再滚回到合并前,这样通常更方便些:可一次完成所有分支里的改名,同时避免被一大堆各种分支搞晕。(方法来源于stackoverflow,具体链接忘了)。详细参考:Pro Git-重写历史

子目录变根目录

要把某个子目录foodir/ 下的所有文件(包含其历史),独立出去,成为一个单独的项目。其它文件自然被丢弃了,所以操作前要把整个仓库备份一下,或者在克隆的新仓库上操作。

git filter-branch --subdirectory-filter foodir -- --all

整个项目作为项目的子目录(根目录改子目录)

因为功能扩充、重构等原因,要把项目所有文件移到子目录里,git mv 不能被真正的跟踪。按如下操作,可移到newsubdir子目录中

git filter-branch --index-filter \
'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

参看git联机文档 git filter-branch --help

合并提交(把多次commit合并成一个)

变基(rebase)相关操作,如 git rebase -i HEAD~3 更多参考git-book 重写历史

修改提交历史中的邮箱地址

git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD

删除指定姓名的所有提交历史

这样作法不好,跟这人得多大的仇

git filter-branch --commit-filter '
       if [ "$GIT_AUTHOR_NAME" = "Darl McBribe" ];
       then
               skip_commit "$@";
       else
               git commit-tree "$@";
       fi' HEAD

从所有git历史版本中修改某个文件中指定内容(字串替换)

某个文件已经有多个历史版本,但里面有某些宜的内容(比如用户名密码),因此希望保留某完整的历史,而不是简单的将其所有历史中删除,而只把指定字符串替换掉。

git filter-branch --tree-filter '
  if [ -f create_table_sql.txt ];
  then
    sed -i "s/realpasswd/fackstring/g" create_table_sql.txt;
  fi' HEAD

自由的编辑(交互式,而非前面的批处理式)

  1. git rebase -i <commit> 命令打开交互式 rebase 编辑器(若要从第一次提交开始修改,可以使用 git rebase -i --root 命令)。
  2. 在编辑器中,将需要修改的提交行的前缀由 pick 改为 edit,然后保存并关闭编辑器。
  3. Git 将会逐个应用每个提交,并在需要修改的提交上停止。在停止处,可以自由的编辑,然后使用 git commit --amend 命令修改提交,或使用 git reset HEAD~ 命令取消提交并将文件恢复到未提交的状态。
  4. 如果把新近的 commit 拉到早期历史中,其日期将维持,这样插在历史记录显得很突兀;可以使用 --date 参数任意指定。不过日期格式 GIT_COMMITTER_DATE 很不方便手写,可以在shell里通过 date -R -d "2020-05-15 20:30:40" 转换,此二者是一致的,参看前面第一节中所述。
  5. 完成修改后,使用 git rebase --continue 命令继续 rebase 操作,直到所有的提交都被修改或应用。
  6. 如果在 rebase 过程中出现任何问题,可以使用 git rebase --abort 命令取消 rebase 操作并回到修改前的状态。

.EOF.

CentOS 7下安装pptp服务端手记

环境,初装的阿里云ECS最低配机型,CentOS 7 x64  (兼及linode的CentOS 7)

主要配置步骤

1. 安装前检查系统支持

a. 在安装之前查看系统是否支持PPTP

modprobe ppp-compress-18 && echo success

应该输出:success

yum install kernel-devel

b. 是否开启TUN/TAP

cat /dev/net/tun

应该输出:cat: /dev/net/tun: File descriptor in bad state

c. 是否开启ppp

cat /dev/ppp

应该输出:cat: /dev/ppp: No such device or address

如果环境不满足上面3个条件,表示很可能不支持pptp。  例外:linode的xen、kvm服务器,也是支持的pptp的。可能是linode内核是定制的,并不是外部ko模块,与原版CentOS表现有所不一致。

2. 安装必要包

a. 首先安装epel源

yum install epel-release

b. 安装pptp相关包

yum install ppp pptpd net-tools iptables-services

3. 修改相关配置文件

a. 主配置文件 /etc/pptpd.conf

结尾处增加如下两行,分别是pptp服务的虚拟网段网关,及分配给客户端的地址范围。

localip 192.168.9.1
remoteip 192.168.9.101-199

b. pptpd配置文件/etc/ppp/options.pptpd,结尾增加两行,给虚拟网段用的dns服务,可以使用主机商提供的dns服务器地址。

ms-dns 100.100.2.136
ms-dns 100.100.2.138

如果是linode等海外服务器,可以使用谷歌的公共dns服务器地址

ms-dns 8.8.8.8
ms-dns 8.8.4.4

c. 设置pptpd vpn服务器用户名密码,编辑文件 /etc/ppp/chap-secrets, 每行一套帐号,该文件默认有简短说明。一行帐号行示例如下,以空格分隔的4个字段:第1、3是用户名密码,其他两字段是星号

user1 * 111222333 *

d. 服务器允许ip转发内核,编辑配置文件/etc/sysctl.conf,增加如下一行

net.ipv4.ip_forward=1

4. 设置开机自动启动 pptpd, iptables,

ln -s /usr/lib/systemd/system/pptpd.service /etc/systemd/system/multi-user.target.wants/
ln -s /usr/lib/systemd/system/iptables.service /etc/systemd/system/multi-user.target.wants

 

5. iptables配置网络

a. iptables配置,配置虚拟网段NAT支持。如果pptp客户端不需要上网,可以忽略本步骤。

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

,注意其中的eth0是本机网卡设备名,按实际情况修改;按虚拟网段设置NAT,如下

iptables -t nat -I POSTROUTING -s 192.168.9.0/24 -o eth0 -j MASQUERADE

b. 开放pptp端口1723,允许转发

iptables -I INPUT 7 -m state --state NEW -p tcp --dport 1723 -j ACCEPT
iptables -P FORWARD ACCEPT

c. 保存iptables规则

service iptables save

6. 阿里云ECS可能还需要几项特别设置

a. 如果windows下连接pptp,如果遇到519错误,是因为缺少内核模块 ip_nat_pptp ,运行modprobe ip_nat_pptp 即可加载,但最好设置开机自动加载:新建文件 /etc/modules-load.d/ip_nat_pptp.conf 内容为如下一行

ip_nat_pptp

b. 可能还要重建ppp文件:

rm /dev/ppp
mknod /dev/ppp c 108 0

c. 阿里云机器还要修改mtu:修改文件/etc/ppp/ip-up,在exit 0 前加入一行:

ifconfig $1 mtu 1500

d. 阿里云控制台里的安全区域,看上去跟防火墙或iptables类似的东西,要开启相应的端口。

7. 启动服务,加载相关匹配文件等

sysctl -p
systemctl start pptpd

或者单粗暴的reboot重启机器也行

域名服务商、注册续费优惠码等

国内注册商有很多,但已经很多年不用了,多方面原因,可以自行google. 这里只说国外注册。更便宜,随便迁移,经常有有优惠码,更便宜。

最广为人行的是godaddy(狗爹),号称全球最大域名商。不过他们家域名续费价格通常有点高。还有name.com, namecheap等无数多个。

通常各域名商的初注册、域名转入,价格会比较便宜,所以一个捡漏的办法:每年换一次注册商!虽然有点不厚道,但确实节省了成本。其实转入60天后就可以下一次转入,这样多转几次,也相当于折腾着续费多年,不至于忘续费而丢掉。

域名商 name.com WHOIS隐私保护 优惠码 PRIVACYPLEASE  ,效果是隐私保护免费!

excel公式实现:根据当前单元格偏移位置引用计算、多条件查找

根据当前单元格偏移位置引用计算

直接上公式示例

=INDIRECT(ADDRESS(ROW()-1,COLUMN()))

作用:引用当前单元格上一行同列的值。
原理:自己查excel自带帮助的公式说明。
特点:可以无脑的将该公式粘贴到任意位置,即做相对引用,不受表格其他内容、位置的影响。
使用场景示例:如下图所示,尾行是计算周变化值/比例。选中格事实就是=B706-B698。每周会插入8行数据。使用了上面偏移位置方案,就不用每次更新下面公式,省心且不出错。

根据相对位置定位一个单元格或一个区域

函数:OFFSET(reference, rows, cols, [height], [width])
reference是一个单元格,相对于它、偏移指定行数rows和列数cols,然后返回一个高height、宽width的区域。 height, width 省略默认为1,即返回一个单元格。rows, cols 可以为负数,表示反方向。

所以,非常适用于一组行数不确定的区域的计算。比如上例截图里的每组是周,固定为7行,如果是月,那就可以先计算一下行数,再通过 OFFSET 函数计算出区域再做汇总计算,避免痛苦地更新公式。

 

多条件查找

本方法来源于:https://www.zhihu.com/question/41820039/answer/93329442 在此表示感谢。

通用公式

=lookup(1,0/((条件1)*(条件2)*(条件3)),结果区域)

原理:参看出处说明

另外还有更多方法

华为mate 9折腾经验记录:google服务,twrp recovery, root等

使用android的历史,从最早的山寨平板开始,到使用近三年的glaxy nexus,再到nesux 5,从今年2月份开始换mate 9,至今已经半年多,记录一下经验。

mate 9的粗略印象

电池比较大,屏幕也略嫌大。华为对android做的定制,基本上还比较合理,自带的系统应用,也比较有用,比如名片扫描、二维码扫描、滚动截屏、天气、等。不便处也有,举例,最近应用列表下的清理按钮,太容易误点到,令人崩溃。

基本使用

网络:shadowsocks,kcptun,谁用谁知道。

重置与备份:华为手机助手,可以免root做整机配置备份,类似于固件工具箱的应用备份功能。

重置手机:可以通过eRecovery在线安装系统,官方不提供刷机包。

Google服务

google服务是绝对不可少的,即使在如此恶劣的网络环境下,借助shadowsocks神器。以前的系统,可能装第三方的google服务安装器,免root环境安装;最新的版本已经自带google服务了,所以整机备份后,通过eRecovery重装系统,再还原备份。

开机启动选项

Recovery: 关机状态下,按住音量上键+电源键开机,出现开机画面1-2秒后,放开电源键,音量上键继续按住不动,直至进入recovery;
出现开机画面即放开音量上键则进入恢复出厂、清空cache界面。
音量下键+电源,进入fastboot, 似乎解锁后就不能用了。

解锁等

fastboot 命令提示:failed <remote: command not allowed> 通常这种情况关闭手机找回就可以正常解锁了,选项在 “设置-云服务” 中。  from http://club.huawei.com/thread-12177115-1-1.html

第三方Recovery, Root

习惯使用twrp的recovery,不过twrp官方并不支持mate 9,所幸有高手做的mate9全系列适配版,当前已知最新版本为 3.1.0,(支持设备:MHA-L29 devices, MHA-L09 devices, MHA-AL00 devices, MHA-TL01 devices, LON-L29 devices, LON-AL00 devices)。直接下载链接 twrp-3.1.0-1-hi3660.img 。当前版本不支持机身存储的加密方式,所以要刷root包时,推荐使用tf卡。具体是:在twrp主界面 - install ,点下按钮切换存储器为sd/tf卡(默认是机身存储,sdcard目录里全是加密字符串)。

参考xda帖子:https://forum.xda-developers.com/mate-9/development/recovery-unofficial-twrp-huawei-mate-9-t3515617  ,本帖中有root的方法,使用的是Phh's superuser方案,只是因为习惯使用的是 SuperSU,故不采用。

root ,使用SuperSU的方案。当前版本 SuperSU 2.82-SR1,已经官方支持mate 9,直接下载SuperSU 2.82-SR1,注意需要 使用TWRP 3.1.0 ,系统固件 B182+ 以上版本。似乎有点诡异,以前刷这个无限重启,只好erecovery还原折腾;这次先刷了前面的phh's supersuer,因为没看到root管理器而装了supersu,但提示su文件被使用,于是死马当活马医而再刷supersu 2.82-SR1的zip包,竟然正常了,重启两次就进入系统。170920

参考xda帖子 https://forum.xda-developers.com/mate-9/development/root-supersu-2-79-t3573155

其它参考 http://www.teamandroid.com/2017/04/11/root-huawei-mate-9-emui-50-android-70-nougat/

180302后记:事实上,已经很久没有root了,之前折腾root方案的目的,其实只有一个:使用google位置记录,通过location_enable应用及xposed模块都不行;然而并没成功。于是不再root.

(个人探索)卸载windows 10自带应用方法

windows10自带了很多应用,说实在的,实在烂得让人失去吐槽的兴趣,卸载是最好的对策。网上有一些卸载方案,比如google搜索出的这两篇

感觉这里的方案有点简单粗暴,不够优雅。突然发现了一个更好的办法,利用windows任务管理器,只卸载让你感到恶心的那些“应用”。

方法如下:

  1. 如果你发现某个恶心的“应用”被打开了(比如双击打开某个视频文件后,打开了“电影与电视”),先不要关闭它。
  2. 打开windows任务管理器,进入“进程”选项卡,在“应用”一组里,找到上述应用,点右键 - 属性
  3. “属性”对话框的“常规”选项卡里的“位置”一项,是一个路径,形式如 C:\Program Files\WindowsApps\***** 最后一级目录(即前面星号代替部分)就是应用的包名,将包名复制到剪贴板
  4. 以管理员身份启动Powershell(可以在开始菜单里找到 Windows Powershell,点右键 - 以管理员身份运行),运行 Remove-AppxPackage 包名
  5. 完成。

这样就只卸载你不需要的那些应用。

补记@2023/04/25

上文内容有点太老了,近几年已经有相当多更完善的方案,比如这篇  卸载重装 Windows 10 内置应用的最全方法,包含有卸载与恢复的方法,核心内容如下:

使用的 PowerShell 命令

Get-AppxPackage:用于获得 Win 10 系统内置应用信息。
Remove-AppxPackage:用于删除 Win 10 系统内置应用。
Add-AppxPackage:用于安装 Win 10 系统内置应用。

1 查询并记录安装下来有哪些应用,算是备份

Get-AppxPackage >> D:\win10_app_list_full.txt

或者精简的格式(只包含应用名与包的全名)

get-appxpackage | Select Name, PackageFullName >> D:\win10_app_list.names.txt

2 按包名卸载应用,与前述一样Remove-AppxPackage {包全名}

也可按包名关键词卸载 Get-AppxPackage *{包名关键词}* | Remove-AppxPackage

如 Get-AppxPackage *xboxapp* | Remove-AppxPackage 卸载xboxapp相关的

3 重新装回卸载的应用

从备份的应用名称文件中找到包名,查出其对应的InstallLocation,比如查计算器windowscalculator:运行 Get-AppxPackage -allusers *windowscalculator* ,结果输出里的 InstallLocation 一行是个长长的文件路径,放到下面命令里(即引号中的部分,太丑陋而简略了),运行即可安装回来

Add-AppxPackage -register "C:\ProgramFiles\....xml" -DisableDevelopmentMode

如果要一次性恢复所有应用,即恢复所有默认自带的应用,则可运行如下

Get-AppxPackage -AllUsers| Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}

运行中应该有报错,不用理会,完成后要重启windows生效。