BNU-FZH

fengzhenhua@outlook.com

名词解释

\(SU_n(q)\)群,是指“The special unitary group”, 翻译成中文就是“特殊幺正群”。 同理\(SO_n(q)\)群,是指"The special orthogonal group", 翻译成中文就是“特殊正交群”。酉矩阵(unitary matrix)也叫幺正矩阵, 对它取复共轭再转置则等于逆矩阵,也即是幺正矩阵的转置共轭等于它的逆。当矩阵元为实数时也叫正交矩阵(orthogonal matrix),它的共轭就是它自己,所以转置即得到逆矩阵,这也就表现为矩阵的行向量间为正交关系,列向量间也为正交关系。

英文介绍

The special unitary group \(SU_n(q)\) is the set of \(n×n\) unitary matrices with determinant \(+1\) (having \(n^2-1\) independent parameters). SU(2) is homeomorphic with the orthogonal group \(O_3^+(2)\). It is also called the unitary unimodular group and is a Lie group.

Special unitary groups can be represented by matrices

\[\begin{equation}\label{eq:sug0} \begin{bmatrix} a & b \\ -\overline{b} & \overline{a} \end{bmatrix} \end{equation}\]

where \(\overline{a}a+\overline{b}b=1\) and \(a,b\) are the Cayley-Klein parameters. The special unitary group may also be represented by matrices

\[\begin{equation}\label{eq:sug1} U(\xi,\eta,\zeta)= \begin{bmatrix} e^{i\xi}\cos\eta & e^{i\zeta}\sin\eta \\ -e^{-i\zeta}\sin\eta & e^{0i\xi}\cos\eta \end{bmatrix} \end{equation}\]

or the matrices

\[\begin{equation}\label{eq:sug2} U_x(\frac{1}{2}\phi)= \begin{bmatrix} \cos(\frac{1}{2}\phi) & i\sin(\frac{1}{2}\phi) \\ i\sin(\frac{1}{2}\phi) & \cos(\frac{1}{2}\phi) \end{bmatrix} \end{equation}\]

\[\begin{equation}\label{eq:sug3} U_y(\frac{1}{2}\phi)= \begin{bmatrix} \cos(\frac{1}{2}\beta) & \sin(\frac{1}{2}\beta) \\ -\sin(\frac{1}{2}\beta) & \cos(\frac{1}{2}\beta) \end{bmatrix} \end{equation}\]

\[\begin{equation}\label{eq:sug4} U_z(\xi)= \begin{bmatrix} e^{i\xi} & 0 \\ 0 & e^{-i\xi} \end{bmatrix} \end{equation}\]

参考引文

一、 修改数组的形状

1、重塑数组形状

方法 作用
reshape() 不修改原数组的形状,返回一个视图,会影响原数组的数据
resize() 直接作用于原数组
shape() 直接作用于原数组

若不理解视图,可以通过 视图与拷贝 这篇博客进行了解。

  • ndarry.reshape()
1
2
3
4
5
6
ndarry.reshape(shape)
shape:填入生成的数组形状(元组)

特点:
1、有返回值,返回一个视图
2、不直接作用于原数组(不改变原数组的形状),但影响原数组的元素

代码:

1
2
3
4
5
6
7
import numpy as np
n1 = np.array([[2,4,3,2],[8,4,2,9],[8,3,4,9]])
# 形状
n1.shape
# (3, 4)
# reshape
n1.reshape((4,3))
  • ndarry.resize()
1
2
3
4
5
6
7
resize(shape) :谨慎使用!

shape:填入生成的数组形状(元组)

特点:
1、无返回值
2、直接作用于原数组(改变原数组的形状)

代码

1
2
3
4
5
6
n1 = np.array([[2,4,3,2],[8,4,2,9],[8,3,4,9]])
n1.resize(2,2,3)

# n1形状已修改
n1.shape
# (2, 2, 3)
  • ndarry.shape
1
2
shape
通过属性直接赋值修改(改变原数组的形状)

代码

1
2
3
4
5
6
n1 = np.array([[2,4,3,2],[8,4,2,9],[8,3,4,9]])
# 数组的原始形状
n1.shape
# (4, 3)
n1.shape = (2,6)
n1

2、多维数换向一维数组转换

  • ndarry.ravel()
1
2
3
4
5
6
7
ndarry.ravel(order=)

当不设置参数order,默认将数组横向展平为一维数组
当设置参数order = 'F',即为将数组纵向展平为一维数组

注意:
使用ravel函数修改形状,得到一个视图,不会改变原数组的形状,但会会改变原数组中的元素!

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
n1
# array([[2, 4, 3],
# [2, 8, 4],
# [2, 9, 8],
# [3, 4, 9]])
# 横向展平为一维数组
n1.ravel()
# array([2, 4, 3, 2, 8, 4, 2, 9, 8, 3, 4, 9])
# 纵向展平为一维数组
n1.ravel(order='F')
# array([2, 2, 2, 3, 4, 8, 9, 4, 3, 4, 8, 9])
# 原数组形状未改变
n1
# array([[2, 4, 3],
# [2, 8, 4],
# [2, 9, 8],
# [3, 4, 9]])
# 修改元素
n1.ravel()[3] = 77
# 原数组数据被修改
n1
# array([[ 2, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])
  • ndarry.flatten()
1
2
3
4
5
6
7
8
ndarry.flatten(order=)

当不设置参数order,默认为将数组横向展平为一维数组
当设置参数order = 'F',则将数组纵向展平为一维数组

注意:
使用flatten函数不会对原数组产生任何影响
(原数组形状和元素都不受其影响)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
n1
# array([[ 2, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])
# # 将数组横向展平成一维数组
n1.flatten()
# array([ 2, 4, 3, 77, 8, 4, 2, 9, 8, 3, 4, 9])
# 展平时候的形状
n1.flatten().shape
# (12,)
# 将数组纵向展平成一维数组
n1.flatten(order='F')
# array([ 2, 77, 2, 3, 4, 8, 9, 4, 3, 4, 8, 9])
# flatten修改元素数值
n1.flatten()[1] = 6
# 不影响原数组的形状和元素数据
n1
# array([[ 2, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])
  • ndarry.reshape(-1)

函数说明

1
2
3
4
5
6
7
8
9
10
11
12
n1.reshape(-1)
-1:表示自动计算

n1.reshape(m,-1)
指定行为m,列自动计算

n1.reshape(-1,n)
指定列为n,行自动计算

注意:
1、不影响原数组的形状
2、影响原数组的元素

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
n1
# array([[ 2, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])
# 横向展平
n1.reshape(-1)
# array([ 2, 4, 3, 77, 8, 4, 2, 9, 8, 3, 4, 9])
# 同n1.reshape(-1) 数组只有一个维度,自动计算长度
n1.reshape(-1,)
# array([ 2, 4, 3, 77, 8, 4, 2, 9, 8, 3, 4, 9])
# 指定列数,自动计算行数
n1.reshape(-1,6)
# array([[ 2, 4, 3, 77, 8, 4],
# [ 2, 9, 8, 3, 4, 9]])
# 指定行数
n1.reshape(3,-1)
# array([[ 2, 4, 3, 77],
# [ 8, 4, 2, 9],
# [ 8, 3, 4, 9]])
# 不改变原数组的形状
n1
# array([[ 2, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])
# 通过reshape修改元素,原数组元素数据产生变化
n1.reshape(-1,)[0] = 12
n1
# array([[12, 4, 3],
# [77, 8, 4],
# [ 2, 9, 8],
# [ 3, 4, 9]])

3、 增加一个维度

  • np.newaxis() 所在位置增加一个维度

一维扩展为二维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 一维度数组
n2 = np.arange(10)
n2
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
n2.shape
# (10,)
# 行方向增加一个维度
n2[np.newaxis,:]
# array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
n2[np.newaxis,:].shape
# (1, 10)
# 列方向增加一个维度
n2[:,np.newaxis]
# array([[0],
# [1],
# [2],
# [3],
# [4],
# [5],
# [6],
# [7],
# [8],
# [9]])

n2[:,].shape
# (10, 1)

二维扩展为三维

1
2
3
4
5
6
7
8
9
# 二维度数组
n2 = np.arange(10).reshape(2,5)
n2.shape
# (2, 5)
n2[np.newaxis,:,:]
# array([[[0, 1, 2, 3, 4],
# [5, 6, 7, 8, 9]]])
n2[np.newaxis,:,:].shape
# (1, 2, 5)

以此类推,将小维度数组扩展成更多维的数组。

4、数组行列转置

  • ndarray.T 属性
1
2
3
4
5
6
7
8
9
10
n2
# array([[0, 1, 2, 3, 4],
# [5, 6, 7, 8, 9]])
# ndarray.T 将数据按照对角线进行行列倒置,行变成了列,列变成了行
n2.T
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])
  • ndarray.transpose()
1
2
3
4
5
6
7
# 同ndarray.T 
n2.transpose()
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])
  • ndarray.swapaxes(1,0)
1
2
3
4
5
6
7
# 必须填入两个参数,进行行列转换
n2.swapaxes(1,0)
# array([[0, 5],
# [1, 6],
# [2, 7],
# [3, 8],
# [4, 9]])

二、数据的拼接(合并)

  • np.hstack() 水平拼接
1
2
3
4
np.hstack(tup) 数组的水平拼接
水平拼接即为横向拼接,数组的行数要一致

tup:ndarray序列

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 准备数组1
a1 = np.array([[3,4,5],[2,4,1],[8,9,4]])
a1
# array([[3, 4, 5],
# [2, 4, 1],
# [8, 9, 4]])
# 准备数组2
a2 = np.array([[7,3,1,5],[3,9,4,1],[2,8,7,4]])
a2
# array([[7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4]])
# 进行水平拼接
np.hstack([a1,a2])
# array([[3, 4, 5, 7, 3, 1, 5],
# [2, 4, 1, 3, 9, 4, 1],
# [8, 9, 4, 2, 8, 7, 4]])
  • np.vstack() 竖直拼接
1
2
3
4
np.vstack(tup) 数组的水平拼接
竖直拼接即为纵向拼接,数组的列数要一致

tup:ndarray序列

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 准备数组1
a2 = np.array([[7,3,1,5],[3,9,4,1],[2,8,7,4]])
a2
# array([[7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4]])
# 准备数组2
a3=np.arange(12).reshape(3,4)
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
# 进行竖直拼接
np.vstack((a3,a2))
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11],
# [ 7, 3, 1, 5],
# [ 3, 9, 4, 1],
# [ 2, 8, 7, 4]])
  • np.concatenate() 指定数组的拼接方向
1
2
3
4
np.concatenate((a1, a2, ...), axis=0, out=None)

axis = 0 :按照行的方向进行拼接,竖直拼接
axis = 1 :按照列的方向进行拼接,横向拼接

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 准备数组1
a1 = np.array([[3,4,5],[2,4,1],[8,9,4]])
a1
# array([[3, 4, 5],
# [2, 4, 1],
# [8, 9, 4]])
# 准备数组2
a2 = np.array([[7,3,1,5],[3,9,4,1],[2,8,7,4]])
a2
# array([[7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4]])
# 按照列的方向进行拼接,横向拼接
np.concatenate((a1,a2),axis = 1)
# array([[3, 4, 5, 7, 3, 1, 5],
# [2, 4, 1, 3, 9, 4, 1],
# [8, 9, 4, 2, 8, 7, 4]])
# 准备数组3
a3=np.arange(12).reshape(3,4)
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11]])
# 按照行的方向进行拼接,竖直拼接
np.concatenate((a3,a2),axis = 0)
# array([[ 0, 1, 2, 3],
# [ 4, 5, 6, 7],
# [ 8, 9, 10, 11],
# [ 7, 3, 1, 5],
# [ 3, 9, 4, 1],
# [ 2, 8, 7, 4]])

三、 数据的复制

  • np.tile(ndarry,(m,n)) 指定数组的方向复制
1
2
3
4
np.tile(ndarry,(m,n))
tile是瓷砖的意思,顾名思义,这个函数就是把数组像瓷砖一样铺展开来。
m:表示按照行的方向进行复制,铺展m次
m:表示按照列的方向进行复制,铺展n次

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
a2
# array([[7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4]])

# 按照行的方向进行复制,铺展3次,竖直铺展
np.tile(a2,(3,1))
# array([[7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4],
# [7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4],
# [7, 3, 1, 5],
# [3, 9, 4, 1],
# [2, 8, 7, 4]])
# 按照列的方向进行复制,铺展2次,横向铺展
np.tile(a2,(1,2))
# array([[7, 3, 1, 5, 7, 3, 1, 5],
# [3, 9, 4, 1, 3, 9, 4, 1],
# [2, 8, 7, 4, 2, 8, 7, 4]])
# 分别按照行列方向进行铺展
np.tile(a2,(2,3))
# array([[7, 3, 1, 5, 7, 3, 1, 5, 7, 3, 1, 5],
# [3, 9, 4, 1, 3, 9, 4, 1, 3, 9, 4, 1],
# [2, 8, 7, 4, 2, 8, 7, 4, 2, 8, 7, 4],
# [7, 3, 1, 5, 7, 3, 1, 5, 7, 3, 1, 5],
# [3, 9, 4, 1, 3, 9, 4, 1, 3, 9, 4, 1],
# [2, 8, 7, 4, 2, 8, 7, 4, 2, 8, 7, 4]])

参考文章

CSV 文件格式是存储数据的最简单和有用的格式, 本文记录将 NumPy 数组保存为 CSV 文件的不同方法。

使用 Dataframe.to_csv() 将 NumPy 数组转换为 CSV

该方法用于将 Dataframe 写入 CSV 文件中。将数组转换为 pandas Dataframe ,然后将其保存为 CSV 格式。

1
2
3
4
5
6
7
8
9
10
11
# import necessary libraries
import pandas as pd
import numpy as np
# create a dummy array
arr = np.arange(1,11).reshape(2,5)
# display the array
print(arr)
# convert array into dataframe
DF = pd.DataFrame(arr)
# save the dataframe as a csv file
DF.to_csv("data1.csv")

使用 numpy_array.tofile() 将一个 NumPy 数组转换为 CSV

该方法用于将一个数组写入文件中。创建一个数组,然后将其保存到 CSV 文件中。

1
2
3
4
5
6
7
8
9
10
# import the necessary library
import numpy as np
# create a dummy array
arr = np.arange(1,11)
# display the array
print(arr)
# use the tofile() method
# and use ',' as a separator
# as we have to generate a csv file
arr.tofile('data2.csv', sep = ',')

使用 numpy.savetext() 将一个 NumPy 数组转换为 CSV

该方法用于保存一个数组到一个文本文件。创建一个数组,然后将其保存为 CSV 文件。

1
2
3
4
5
6
7
8
# import numpy library
import numpy
# create an array
a = numpy.array([[1, 6, 4],
[2, 4, 8],
[3, 9, 1]])
# save array into csv file
numpy.savetxt("data3.csv", a, delimiter = ",")

使用文件处理将 NumPy 数组转换为 CSV 文件

格式化器通过使用 str.format 函数和一对大括号()将一个或多个替换字段和占位符插入一个字符串中。该值将被插入占位符中,并与作为输入提供给 format函数的字符串连接。 with 是用来写进 CSV 文件的。

1
2
3
4
5
6
7
8
9
10
11
12
# import numpy library
import numpy
 
# create an array
a = numpy.array([[1, 6, 4],
[2, 4, 8],
[3, 9, 1],
[11, 23, 43]])
# save array into csv file
rows = ["{},{},{}".format(i, j, k) for i, j, k in a]
text = "\n".join(rows)
with open('data3.csv', 'w') as f: f.write(text)

参考文章

Next 是一款优秀的 Hexo 博客主题。 随时间的推移,Next 主题已经升级到了 Next 8.21.1, 但是升级主题的时候有时候会遇到错误,比如:

造成这些问题的主要原因在于,Next 主题升级必然有许多要修改的源码或增加的功能。而按官网的教程 theme-next 的建议,升级 Next 主题时应当把原来的主题配置文件 themes/next/_config.yml 复制到根目录,也就是和 themes 一个目录,并且命名为 _config.next.yml, 这样升级主题后配置文件由于没被覆盖而得以保留自定义设置。但是这造成另一个问题,假如升级前后两个版本的差异过大,导致有些功能上的删减,那原来的配置有可能就不再被新主题兼容,这样再生成博客就会导致出错。同时,由于配置文件没有被修改,新配置就不会生效,所以升级后应当将原配置文件 _config.next.ymlthemes/next/_config.yml 对比,找出不同,修改成新主题的配置方式,这样就可以正常使用新系统了。

文本中的重复行,基本上不是我们所要的,所以就要去除掉。使用uniq的时候要注意以下二点:

uniq 的语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
用法:uniq [选项]... [输入文件 [输出文件]]
从 <输入文件>(或标准输入)中过滤内容相同的相邻的行,
并写到 <输出文件>(或标准输出)。

不带选项时,内容相同的行将仅输出一次。


长选项的必选参数对于短选项也是必选的。
-c, --count 在每行之前加上该行的重复次数作为前缀
-d, --repeated 只输出重复的行,每组重复的行输出一次
-D 输出所有重复的行
--all-repeated[=方法] 类似 -D,但支持在每组重复的行之间添加一行空行;
方法={none(默认),prepend,separate}
-f, --skip-fields=N 不要比较前 N 个字段
--group[=方法] 分组输出所有项目,每组之间用空行分隔;
方法={separate(默认),prepend,append,both}
-i, --ignore-case 比较时忽略大小写
-s, --skip-chars=N 不要比较前 N 个字符
-u, --unique 只输出不重复(内容唯一)的行
-z, --zero-terminated 以 NUL 空字符而非换行符作为行分隔符
-w, --check-chars=N 每行最多比较 N 个字符
--help 显示此帮助信息并退出
--version 显示版本信息并退出

字段指的是空白字符(通常是空格和/或制表符)的序列,后跟非空白字符的序列。
程序将先跳过字段 (--skip-fields),后跳过字符 (--skip-chars)。

除非重复的行是相邻的,否则 "uniq" 将无法检测到它们。
您可能需要事先对输入进行排序,或使用 "sort -u" 而无需接着使用 "uniq"

GNU coreutils 在线帮助:<https://www.gnu.org/software/coreutils/>
请向 <http://translationproject.org/team/zh_CN.html> 报告任何翻译错误
完整文档 <https://www.gnu.org/software/coreutils/uniq>
或者在本地使用:info '(coreutils) uniq invocation'

uniq 处理文件重复数据

经常有这样的需求:两个文本文件要求取重复的行或只取不重复的,但是uniq只能处理相邻重复的行,所以需要借助于sort命令,先排序。利用现存两个文件 file1file2,生成一个新的文件。

取出两个文件的并集(重复的行只保留一份)

1
cat file1 file2 | sort | uniq

取出两个文件的交集(只留下同时存在于两个文件中的文件,重复行)

1
cat file1 file2 | sort | uniq -d

删除交集,留下其他的行(非重复行)

1
cat file1 file2 | sort | uniq -u

注意:对文本操作时,若域中为先空字符(通常包括空格以及制表符),然后非空字符,域中字符前的空字符将被跳过。

矢量分析在电动力学中具有无可替代的作用和地位,但是学过电动力学的人都知道 Maxwell 方程组, 而今天我却要为 Maxwell 方程组的积分形式重申一下它们的名字。

牛顿-莱布尼兹公式

\[\begin{equation}\label{eq:n-l} \int_{\partial \gamma} f=\int_\gamma (\nabla f)\cdot ds \end{equation}\]

梯度场通常对应于静电场,因为电场强度是电势的梯度,它的典型特点就是积分与路径无关,或都说存在原函数,满足牛顿-莱布尼兹公式。

斯托克斯公式

\[\begin{equation}\label{eq:stokes} \int_{\partial S}A\cdot ds=\int_{S}(\nabla \times A)\cdot d\sigma \end{equation}\]

这个公式比较厉害,用斯托克斯一个人的名字命名. 这个公式描述的是磁感应强度是矢势的旋度, 它把磁通量用矢势的线积分表示了出来。

高斯-奥斯特罗格拉德斯基公式

\[\begin{equation}\label{eq:g-a} \int_{\partial V}V\cdot dd\sigma =\int_V (\nabla\cdot B)dV \end{equation}\]

这个公式,多数人都知道是高斯公式,但是它却还有另一个人:奥斯特罗格拉德斯基,这点还是需要大家注意的。唉,看来,起名字不能太长,不然不容易被人记住。

作为一名科研人员,从一些知名期刊下载论文是一个重要的工作。然而,有些网站要么打不开,要么特别慢,然后这些科研网站又都是正规的网站。本文发布一款shell脚本来彻底解决这一痛点。

注意:本文发布有脚本目前仅支持Arch Linux,主要是安装依赖关系,其他Linux发行版可以自行修改。暂无发布Windows版的计划,如果您可以用Python实现对Windows的支持,欢迎联系本人共同拓展syndns.sh.

脚本编写思路

当前的网络设备已经完全可以满足大众上网的需求,一些网站为了增加功能等,会默认调用大量的js脚本等,因此打开这个网站时就会附加后台打开若干网站。通过后台链接传输的数据不是很大,现行的网速完全可以几乎瞬时完成,造成访问不畅通的瓶颈在于DNS,因为DNS不断的去解析这些网站包括的所有域名,在来来回回的解析过程中耽误了大量的时间,所以本脚本的核心思路在于解决DNS解析痛点。 整体方法包括:

  • 针对大众: 根据大家常用的网站,把这些网站的IP和域名统一写入本地/etc/hosts, 这样每次访问这些高频网站,系统就会从本地寻址,加快了解析速度。
  • 针对个人: 从firefox导出近几个月的历史记录~/bookmarks-2024-12-02.json, 然后执行syndns, 脚本自动从历史记录中把您自己常用的网站通过谷歌的8.8.8.8解析出可靠的IP列表,并写入到本地文件~/.host_dns_autoadd.txt, 然后syndns会把它载入到内存供dnsmasq调用。
  • 安装 dnsmasq 并启用,实现本地作为 DNS 服务器的功能,同时把 /etc/hosts~/.host_dns_autoadd.txt 中的映射关系统一放入内存 /dev/shm/dnsrecord.txt 文件中, 之后 dnsmasq 每次查询IP就会读取一次文件 /dev/shm/dnsrecord.txt , 而这成为最快的方式。如果不调入内存,那每次查询 IP , 系统都会去读取 /etc/hosts, 这个文件位于硬盘上,所以它的读取速度不是最快的,相对而言固态硬盘要比机械硬盘好很多,但是仍然远不如内存快, 所以调入内存是终极大招。

脚本源码

本文发布之时(2024年12月02日) syndns.sh 版本为 V1.5 , 最新脚本请前往:

syndns.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#! /bin/sh
#
# Program : syndns.sh
# Version : v1.5
# Date : 2024-12-02 11:20
# Author : fengzhenhua
# Email : fengzhenhua@outlook.com
# CopyRight: Copyright (C) 2022-2025 FengZhenhua(冯振华)
# License : Distributed under terms of the MIT license.
#
# 检测软件依懒, 若未检测到,则自动安装
SYNDNS_DEPEND(){
for VAR in $1 ;do
pacman -Qq $VAR &> /dev/null
if [[ $? != 0 ]]; then
sudo pacman -S $VAR
fi
done
}
# 变量
SYN_EXE="/usr/local/bin/${0%.sh}"
SYN_AUTO="$HOME/.config/autostart/${0%.sh}.desktop"
SYN_SUDO="/etc/sudoers.d/01_$USER"
SYN_HOS="/etc/hosts"
SYN_REC=$(grep "addn-hosts" /etc/dnsmasq.conf |grep "/dev/shm/")
SYN_REC=${SYN_REC#*=}
SYN_ADD="$HOME/.host_dns_autoadd.txt"
#
# 主程序
SYNDNS_PROCESS(){
cat $SYN_HOS |grep -v '^$'|grep -v '^#'|sort |uniq -u > $SYN_REC
if [ -e $SYN_ADD ]; then
cat $SYN_ADD |grep '^[0-9]' |grep -v '^$'|grep -v '^#'|sort |uniq -u >> $SYN_REC
fi
echo "$(hostname -i) localhost:" >> $SYN_REC
systemctl is-active --quiet dnsmasq
if [[ $? == 0 ]]; then
sudo systemctl restart dnsmasq.service
else
sudo systemctl start dnsmasq.service
fi
}
# 安装和更新
if [ $# -gt 0 ]; then
if [ $1 == "-i" -o $1 == "-I" ]; then
SYNDNS_DEPEND "dnsutils inetutils dnsmasq jq"
sudo cp -f $0 $SYN_EXE
sudo chmod +x $SYN_EXE
if [ ! -e $SYN_AUTO ]; then
sudo touch $SYN_AUTO
cat > $SYN_AUTO <<EOF
[Desktop Entry]
Name=SynDns
TryExec=syndns
Exec=$SYN_EXE
Type=Application
Categories=GNOME;GTK;System;Utility;TerminalEmulator;
StartupNotify=true
X-Desktop-File-Install-Version=0.22
X-GNOME-Autostart-enabled=true
Hidden=false
NoDisplay=false
EOF
sudo sh -c "cat > /etc/dnsmasq.conf" <<EOA
domain-needed
bogus-priv
resolv-file=/etc/resolv.conf
no-poll
interface=lo
listen-address=127.0.0.1
bind-interfaces
no-hosts
addn-hosts=/dev/shm/dnsrecord.txt
cache-size=9999
port=53
EOA
fi
if [ ! -e $SYN_SUDO ]; then
sudo touch $SYN_SUDO
sudo sh -c "cat > $SYN_SUDO" <<EOB
$USER ALL=(ALL) NOPASSWD: /bin/systemctl start stirling-pdf.service, /bin/systemctl stop stirling-pdf.service, /bin/systemctl restart dnsmasq.service, /bin/systemctl start dnsmasq.service
EOB
fi
elif [[ $1 =~ ".json" ]]; then
Address=($(cat $1|jq -r '.children[]' |grep "\"uri\":"))
Address=(${Address[*]#*//})
Address=(${Address[*]/\"uri\":})
Address=(${Address[*]%%/*})
Address=(${Address[*]%%\"*})
Address=(${Address[*]%%*[0-9]}) # 去除非域名
Address=(`echo ${Address[@]}|sed -e 's/ /\n/g'|sort |uniq`)
if [ -e $SYN_ADD ]; then
rm $SYN_ADD
fi
touch $SYN_ADD
for i in ${Address[*]} ; do
unset SYN_IP
SYN_IP=($(dig @8.8.8.8 +short $i)) # 默认从Google Public DNS 解析历史IP
SYN_IP=(${SYN_IP[*]%%*\.})
for ipc in ${SYN_IP[*]}; do
echo "$ipc $i" >> $SYN_ADD
let j+=1
done
done
SYNDNS_PROCESS
fi
fi
# 默认执行主程序
SYNDNS_PROCESS

使用方法

  1. 将上述脚本 syndns.sh 保存到本地,并赋于执行权限
    1
    sudo chmod+x syndns.sh
  2. 安装脚本
    1
    syndns.sh -i
  3. 导入由firefox生成的历史记录文件:
    1
    syndns ~/bookmarks-2024-12-02.json

注意:Firefox 生成历史记录文件方法,历史管理历史导入和备份备份...

参考文章

awk是一个强大的文本处理工具,它可以根据指定的字段来操作和处理文本数据。下面是使用awk命令去除重复行的步骤:

  1. 使用grep命令搜索匹配的行,并使用awk命令打印其中的一列。
1
grep “pattern” file.txt | awk ‘{print $1}’ > temp.txt  

其中,pattern是你要匹配的模式,file.txt是要搜索的文件,$1表示打印第一列。

  1. 使用sort命令对临时文件进行排序。
1
sort temp.txt > sorted.txt  
  1. 使用uniq命令去除重复行。
1
uniq sorted.txt > result.txt  
  1. 可选:删除临时文件。
1
rm temp.txt sorted.txt  

这样,就可以得到一个去除重复行的结果文件result.txt。

注意: 使用grep命令去除重复行是一种简单的方法,但是它只能根据整行进行去重。如果你需要根据特定的字段或者条件来去重,可以使用其他更强大的工具,如awk、sed或者perl等。

在Linux中,可以使用grep命令去除重复行。grep命令是一个强大的文本搜索工具,但是默认情况下它只会输出匹配的行,而不会去除重复的行。要去除重复行,可以使用grep命令的-v选项结合sortuniq命令来实现。

下面是使用grep命令去除重复行的步骤:

  1. 使用grep命令搜索匹配的行,将输出重定向到一个临时文件。
1
grep “pattern” file.txt > temp.txt  

其中,pattern是你要匹配的模式,file.txt是要搜索的文件。

  1. 使用sort命令对临时文件进行排序。
1
sort temp.txt > sorted.txt  
  1. 使用uniq命令去除重复行。
1
uniq sorted.txt > result.txt  
  1. 可选:删除临时文件。
1
rm temp.txt sorted.txt  

这样,就可以得到一个去除重复行的结果文件result.txt。

本博客已经持续写了三四年了,最初根据网上的教程安装好后就把各种配置写到了自动化脚本 diary.sh 中,然而最近发现升级脚本后会有一串由node.js发出的错误。为了解决这个错误,不断的排除各种小问题,最终决定重新写一下配置博客的基本教程。

Node.js 和 Hexo 简介

Node.js是作为 Hexo程序的依赖而安装的,但是它报错了,经过网络搜索后发现,这是由于我的电脑中安装了最新的Node.js导致的。官网介绍:Node.js® 是一个免费、开源、跨平台的 JavaScript 运行时环境, 它让开发人员能够创建服务器 Web 应用、命令行工具和脚本。 而 Hexo 是一个部署博客的工具,而博客也是发布于网络上的一个 Web 页,所认这个依赖关系就清楚了。

Hexo 的作用是: 把作者写好的 Markdown 文件,使用Node.js渲染成 Web 页,进而可以在网站服务器上部署,实现网络访问的目标。

安装依赖软件

使用 pacman 安装的软件

1
sudo pacman -S nodejs-lts-iron npm git pandoc
  • git 是一个在github上管理源码的必备工具,详细使用请稳步: Git 教程
  • nodejs共有三个版本,分别是nodejs 23.1.0-1(最新版)、nodejs-lts-iron(最新长期支持版)、nodejs-lts-hydrogen(旧的长期支持版). 由于最新版不断有功能添加,其相当不稳定,今天的错误就是由它造成的。旧的长期支持版,又可能不兼容最新的软件,所以安装最新长期支持版就是一个最佳选择。
  • npm 是一个nodejs包管理器,使用它可以安装各种模块,这就很容易为博客添加新的功能。
  • pandoc If you need to convert files from one markup format into another, pandoc is your swiss-army knife.

使用 nodejs 包管理器安装的软件

npm 切换国内源

1
2
3
4
# 国内 淘宝 镜像源
npm config set registry https://registry.npmmirror.com/
# 官方镜像源
npm config set registry https://registry.npmjs.org/

阿里更换了淘宝镜像的域名,原域名https://registry.npm.taobao.org的 SSL 证书已经过期了(2024/01/22),所以我们需要更换最新的源.

安装更好用的包管理器 yarn

1
2
3
4
# 通过 pacman 安装
sudo pacman -S yarn
# 通过 npm 安装
sudo npm install yarn -g

注意:npmJavaScript自带的包管理器,拥有庞大的包注册表,但在性能和安全性方面相对较弱, 特别是下载安装模块的速度相当感人。Yarn 是由 Facebook、Google 等公司共同创建的,旨在解决 npm 的一些痛点,提供更快、更安全、更可靠的包管理体验, 其下载模块非常迅速,所以值得推荐。此外还有pnpm包管理器,但是由于它为了节省硬盘空间而做出了相当大的改变,这导致一些依赖问题不是很好解决,因此不推荐。这三个的区别和优缺点细节,请大家参考本文末的参考文章。

配置 hexo

设置 yarn 的国内源

1
2
3
4
# 国内 淘宝 镜像源
yarn config set registry https://registry.npmmirror.com/
# 官方镜像源
yarn config set registry https://registry.yarnpkg.com/

安装 nrm 镜像源工具

1
sudo yarn global add nrm

nrm使用方法,请参考本文末参考文章。使用nrm test列出各源,并给出源的网速,使用nrm use huawei切换到速度最快的华为源。

安装 hexo 命令

推荐使用速度更快的 yarn
1
2
3
4
# 使用yarn 安装
sudo yarn global add hexo-cli
# 使用 npm 安装
sudo npm install hexo-cli -g

设置本地博客站点

配置 hexo 默认站点

1
2
3
4
mkdir hexo-source
cd ./hexo-source
hexo init
hexo s

完成上面的操作后,在浏览器地址栏输入上述命令生成的本地地址 localhost:4000 就可以看到默认的博客了。

安装 Next 主题

1
2
3
4
cd hexo-source
git clone https://github.com/next-theme/hexo-theme-next themes/next
cd themes/next
git checkout $(git describe --tags $(git rev-list --tags --max-count=1))

切换为 Next 主题

Like all Hexo themes, after you download it, open Hexo config file, find theme option, and change its value to next (or another theme directory name).

hexo-source/_config.yml
1
2
cd hexo-source
theme: next

2024年11月30日, 在测试上述步骤时,发现 启动报错 Cannot find module 'css', 据github上的信息,解决方法是:css 应该被作为 stylus 的依赖包安装。你可以试试重新安装 hexo-renderer-stylus

1
2
3
4
cd hexo-source
yarn add hexo-renderer-stylus
# 也可以使用 npm
npm i hexo-renderer-stylus

本地启动检测

1
2
3
hexo clean 
hexo g
hexo s

参考文章