由于在当前的网络环境下部署了软路由+NAS，由软路由延申到我房间的硬路由在DHCP模式下的网络多了一层NAT，无法向上一层访问，但刷了OpenWrt的硬路由没有常见商用路由器的AP模式切换，让路由器将仅作为无线信号扩展设备。只能逐一对LAN口和WAN口以及防火墙进行设定，下文记录一下操作和背后的原理。 1. 关闭 DHCP 服务 进入 Network → Interfaces。 编辑 LAN 接口，在 DHCP Server 选项卡下，勾选 Ignore interface。 保存并应用。 既然只作为 AP 使用了，自然不需要 DHCP 为局域网内的设备自动分配 IP 地址了 2. 设置 LAN 口 IP（避免冲突） 仍在 LAN 接口的 General Settings 选项卡下： 协议切换为静态地址，把 IPv4 地址改为与上级主路由同一网段且不冲突的 IP。 例如：主路由 IP 是 192.168.2.1，此处可设置为 192.168.2.20。 子网掩码与主路由一致（通常 255.255.255.0）。 网关填写主路由 IP（如 192.168.2.1）。 DNS 服务器可填写主路由 IP 或公共 DNS（如 8.8.8.8）。 保存并应用。 此 IP 地址的存在意义： 提供接口地址管理硬路由本身； 和上级软路由网络层通信。 个人曾经的误区：把 AP 模式和交换机模式混为一谈 3. 关闭防火墙并桥接接口 进入 Network → Firewall。 删除所有防火墙规则，或直接关闭防火墙： 在 General Settings 选项卡，将 Forward、Input、Output 全部设为 ACCEPT。 或直接删除所有防火墙区域（确保不阻断流量）。 4. WAN 和 WAN6 处理 方案一 如果固件里有 switch （交换机）的设置项，可以很方便的通过以下办法来实现将 OpenWrt 设置为交换机 / AP 模式，可以充分利用物理 WAN 口充当 LAN 口来用。 进入 Network → Switch； 将 VLAN ID 1 中的 WAN 口设置为未标记； 删除 Interfaces 中的 WAN 口（包括 WAN6）。 方案二 如果固件里没有 switch （交换机）的设置项，可以进行以下设置，但此设置会浪费一个 WAN 口。 删除 Interfaces 中的 WAN 口（包括 WAN6）； 将连接主路由的网线连接到WAN口。
起因 当我在网页版Jellyfin直接播放视频时，虽然内网能够满足数千兆每秒的网速，这些视频仍然经常卡顿（后面分析是网页播放是直接用NAS的核显解码，但它性能捉急），我就选择直接下载到本地。 由于Jellyfin的限制，下载到本地的文件中文名称是经过URL编码后的，比如其中一个文件为“%E8%83%86%E5%A4%A7%E5%85%9A+S01E07.mkv”，看起来是16进制的Unicode编码。 问题 后续在我清理磁盘时，我发现Windows在图形界面上直接删除此类文件时会异常卡死，而换使用终端命令删除时居然无法定位到这份文件，它就像一个黑户一样钉在了磁盘上，Windows的文件系统拿它丝毫没有办法。这就很奇妙了，之前从未遇到过这种情况。 解决 经过一系列查询检索，最终定位到Windows的一个奇妙特性： Windows系统默认的最大路径长度为260个字符（包括盘符、文件夹名、文件名及分隔符\）。如果文件或文件夹的完整路径超过此限制，系统工具（如资源管理器）可能无法正常操作。 一时间确实有点难绷，这种古老的问题能存续到现在也是神奇。最后索性启动Manjaro Linux，干净利落删除了这个文件。 后面和朋友讨论时，他提出了个更简单的操作方法：使用WSL的终端操作磁盘上的文件。确实可行，连重启切系统的功夫都不用了。
TNND，终于到这里了 Hello World 什么经典开局 程序样例 [aweip@manjaro ~]$ mkdir bin; cd bin [aweip@manjaro ~]$ vim hello.sh #!/bin/bash # Program: # To shows "Hello World!" # History: # 2022/07/24 AweiP First release PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH echo -e "Hello World! \a \n" exit 0 第一行 #!/bin/bash 在宣告这个 script 使用的 shell 名称 程序内容的说明： 除了第一行的『 #! 』是用来宣告 shell 的之外，其他的 # 都是『批注』用途 ，第二行以下就是用来说明整个程序的基本数据。 主要环境变量的宣告 ： 务必要将一些重要的环境变量设定好 主要程序部分 ：这个例子当中，就是 echo 那一行 执行成果告知 (定义回传值) ：利用 exit 这个指令来让程序中断，并且回传一个数值给系统 执行结果 [aweip@manjaro ~]$ sh hello.sh Hello World ! 简单加减乘除求余(即+-*/%) [aweip@manjaro ~]$ vim multiplying.sh #!/bin/bash # Program: # Inputs 2 integer numbers; program will cross these two numbers. # History: # 2022/07/24 PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH echo -e "Input 2 numbers\n" read -p "first: " firstnu read -p "second: " secnu total=$((${firstnu}*${secnu})) echo -e "\nThe result of ${firstnu} x ${secnu} is ==> ${total}" script 的执行方式差异 (source, sh script, ./script) 直接执行的方式来执行 script sh test.sh 使用这种执行方式时， script 是在子程序的 bash 内执行 ，当test.sh 执行完毕后， 子程序 bash 内的所有数据便被移除 （变量作用域仅在fork出的子程序中） 利用 source 来执行脚本：在父程序中执行 source test.sh 善用判断式 利用 test 指令的测试功能 例子：test -e /dmtsai && echo "exist" || echo "Not exist" 关于某个档名的『文件类型』判断 测试的标志 代表意义 -e 该『档名』是否存在？ (常用) -f 该『档名』是否存在且为文件(file)？ (常用) -d 该『文件名』是否存在且为目录(directory)？ (常用) 关于文件的权限侦测，如 test -r filename 表示可读否 (但 root 权限常有例外) 测试的标志 代表意义 -r 侦测该档名是否存在且具有『可读』的权限？ -w 侦测该档名是否存在且具有『可写』的权限？ -x 侦测该档名是否存在且具有『可执行』的权限？ -u 侦测该文件名是否存在且具有『SUID』的属性？ -g 侦测该文件名是否存在且具有『SGID』的属性？ -s 侦测该档名是否存在且为『非空白文件 ​ ....... 利用判断符号 [ ]
Shell 变量的使用与设置 读取变量内容: echo $变量 或 echo ${变量} 设置规则: 变量与内容直接用=连接，两边不留空格; 双引号内特殊字符保留功能; 单引号内为一般字符; [\]转义符+特殊符号(空格,$等)将其变为一般字符; unset+变量名 取消变量设置; export 变量将变量变为环境变量以在子进程运行。 例:实现快速ssh连接服务器 Tencent = "root@42.142.130.**" ssh $Tencent 环境变量的功能 env命令查看默认环境变量与常见环境变量说明; set命令查看所有环境变量: $: 本次shell的pid -> echo $$ ; ?: 上次命令返回值。 locate命令查看语系; read, arry, declare: read [-p] var [-t],使用-p后添加输入提示,-t后添加秒数; declare[-aixr] var,声明变量,aixr对应数组-整型-环境变量-const只读; var[num]="content",数组名+[数字]获得一维数组。 变量内容的删除、取代与替换 (Optional) ${variable#/*local/bin:}: #代表『从变量内容的最前面开始向右删除』，且仅删除最短的那个; echo ${path##/*:}:##变成『从前面删除掉最长的那个数据』; echo ${path%:*bin}: % 符号代表由『最后面开始向前删除』; echo ${path%%:*bin}: %% 代表的则是『从后删除最长的符合字符串』。 命令别名与历史命令 命令别名设定: alias, unalias: alias lm='ls -al | more' 历史命令: history 列出目前内存内的所有 history 记忆 history 列出目前最近的 3 笔资料 history 3 立刻将目前的资料写入 histfile 当中 history -w Bash Shell 的操作环境 bash 的进站与欢迎讯息: /etc/issue, /etc/motd /etc/issue: cat查阅,根据issue内的各代码意义可更改开屏显示的系统信息(Manjaro Linux实操发现为只读文件,chmod修改权限后改动); /etc/motd: 自定义主机启动后显示的讯息。 bash 的环境配置文件 login shell:取得 bash 时需要完整的登入流程的，就称为 login shell。举例来说，要由 tty1 ~ tty6 登入，需要输入用户的账号与密码，此时取得的 bash 就称为『 login shell 』; non-login shell: 取得 bash 接口的方法不需要重复登入的举动，举例来说 以 X window 登入 Linux 后，再以 X 的图形化接口启动终端机，此时那个终端接口并没有需要再次的输入账号与密码，那个 bash 的环境就称为 non-login shell 了. 在原本的 bash 环境下再次下达 bash 这个指令，同样的也没有输入账号密码， 那第二个 bash (子程序) 也是 non-login shell. /etc/profile (login shell 才会读) ~/.bash_profile (login shell 才会读) ...... 终端机的环境设定: stty, set stty [-a] 列出所有的按键与按键内容 (出现 ^ 表示 [Ctrl] 按键); 通配符与特殊符号*, ?, [] 等等,『档名』尽量不要使用到这些字符。 符号 意义 * 代表『 0 个到无穷多个』任意字符 ? 代表『一定有一个』任意字符 [ ] 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符， 可能是 a, b, c, d 这四个任何一个』 [ - ] 若有减号在中括号内时，代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字， 因为数字的语系编码是连续的！ 数据流重导向 概念: 指令可能会由文件读入资料，经过处理之后，再将数据输出到屏幕上,可能分为standard output 与 standard error output ,二者分别代表『标准输出 (STDOUT)』与『标准错误输出 (STDERR)』; 例子: 系统默认有 /etc/crontab 但却无/etc/vbirdsay， 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个指令时， cat 会进行: 标准输出:『指令执行所回传的正确的讯息』,读取 /etc/crontab 后，将该文件内容显示到屏幕上; 标准错误输出:『 指令执行失败后，所回传的错误讯息』,因为无法找到 /etc/vbirdsay，因此在屏幕上显示错误讯息。 问题与解决方式 : 正确或错误的数据都默认输出到屏幕上,导致较为混乱,那能否透过某些机制将这两股数据分开呢?即数据流重导向的功能。 功能及实现 : 数据流重导向可以将 standard output(简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去，而分别传送所用的特殊字符则如下所示: 标准输入 (stdin) :代码为 0 ，使用 < 或 <<; 标准输出 (stdout):代码为 1 ，使用 > 或 >>; 标准错误输出(stderr):代码为 2 ，使用 2> 或 2>>; 例一: ll / ll / > ~/rootfile <==屏幕并无任何信息 ll ~/rootfile <==有个新档被建立了 屏幕没有数据,原本『 ll / 』所显示的数据已经被重新导向到 ~/rootfile文件中 输出文件建立规则: 1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上; 1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上; 2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上; 2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上; 例二: find /home -name .bashrc <==身份是 dmtsai ！ find: '/home/arod': Permission denied <== Standard error output find: '/home/alex': Permission denied <== Standard error output /home/dmtsai/.bashrc <== Standard output 假如要将数据输出到 list 这个文件中,执行『 find /home-name .bashrc > list 』会发现 list 里面存了『正确』的输出数据,屏幕上还是会有错误的讯息出现 ->find /home -name .bashrc > list_right 2> list_error 实现两数据分开传送 命令行执行的判断依据： ; , &&, || cmd ; cmd (不考虑指令相关性的连续指令下达) cmd1 && cmd2 若 cmd1 执行完毕且正确执行($?=0)，则开始执行 cmd2； 若 cmd1 执行完毕且为错误 ($?≠0)，则 cmd2 不执行。 cmd1 || cmd2 若 cmd1 执行完毕且正确执行($?=0)，则 cmd2 不执行； 若 cmd1 执行完毕且为错误 ($?≠0)，则开始执行 cmd2。 管线命令 (pipe) 概念： ls -al /etc | less使用 ls 指令输出后的内容被 less 读取，并利用 less 的功能前后翻动相关的信息 ,管线命令『 | 』仅能处理经由前面一个指令传来的正确信息，也就是 standard output 的信息 。 撷取命令： cut, grep ：撷取讯息通常是针对『一行一行』来分析的 cut cut -d'分隔字符' -f fields cut -c 字符区间 选项与参数： -d ：后面接分隔字符。与 -f 一起使用； -f ：依据 -d 的分隔字符将一段讯息分区成为数段，用 -f 取出第几段的意思； -c ：以字符 (characters) 的单位取出固定字符区间。 grep grep [-acinv] [--color=auto] '搜寻字符串' filename 选项与参数 -a ： 将 binary 文件以 text 文件的方式搜寻数据 ; -c ： 计算找到 '搜寻字符串' 的次数 ; -i ：忽略大小写的不同，所以大小写视为相同; -n ： 顺便输出行号 ; -v ：反向选择，亦即显示出没有 '搜寻字符串' 内容的那一行 ; -color=auto ：可以将找到的关键词部分加上颜色的显示。 排序命令： sort, wc, uniq sort： 可以依据不同的数据型态来排序 sort [-fbMnrtuk] [file or stdin] 选项与参数： -f ：忽略大小写的差异，例如 A 与 a 视为编码相同； -b ：忽略最前面的空格符部分； -M ：以月份的名字来排序，例如 JAN, DEC 等等的排序方法； -n ：使用『纯数字』 进行排序(默认是以文字型态来排序的)； -r ：反向排序； -u ：就是 uniq ，相同的数据中， 仅出现一行代表； -t ：分隔符， 预设是用 [tab] 键来分隔； -k ：以区间 (field) 来进行排序。 uniq： 将重复的资料仅列出一个显示 uniq [-ic] 选项与参数： -i ：忽略大小写字符的不同； -c ：进行计数。 wc： 算输出的讯息的整体数据 wc [-lwm] 选项与参数： -l ： 仅列出行； -w ： 仅列出多少字(英文单字)； -m ：多少字符。 双向重导向： tee ：同时将数据流分送到文件去与屏幕 (screen) tee [-a] file -a ：以累加 (append) 的方式， 将数据加入 file 当中 字符转换命令： tr, col, join, paste, expand 分区命令： split 参数代换： xargs ...... 正则表达式 基础正则表达式 语系对正则表达式的影响 特殊符号 代表意义 [:alnum:] 代表英文大小写字符及数字，亦即 0-9, A-Z, a-z [:alpha:] 代表任何英文大小写字符，亦即 A-Z, a-z [:blank:] 代表空格键与 [Tab] 按键两者 [:cntrl:] 代表键盘上面的控制按键，亦即包括 CR, LF, Tab, Del.. 等等 [:digit:] 代表数字而已，亦即 0-9 [:graph:] 除了空格符 (空格键与 [Tab] 按键) 外的其他所有按键 [:lower:] 代表小写字符，亦即 a-z [:print:] 代表任何可以被打印出来的字符 [:punct:] 代表标点符号 (punctuation symbol)，亦即： " ' ? ! ; : # $... [:upper:] 代表大写字符，亦即 A-Z [:space:] 任何会产生空白的字符，包括空格键, [Tab], CR 等等 [:xdigit:] 代表 16 进位的数字类型，因此包括： 0-9, A-F, a-f 的数字与字符 Linux三剑客之一 —— grep grep 进阶选项 [aweip@Manjaro ~]$ grep [-A] [-B] [--color=auto] '搜寻字符串' filename -A ：后面可加数字， 为 after 的意思，除了列出该行外，后续的 n 行也列出来； -B ：后面可加数字， 为 befer 的意思，除了列出该行外，前面的 n 行也列出来； --color=auto 可将正确的那个撷取数据列出颜色 范例一：用 dmesg 列出核心讯息，再以 grep 找出内含 qxl 那行 [aweip@Manjaro ~]$ dmesg | grep 'qxl' [ 0.522749] [drm] qxl: 16M of VRAM memory size [ 0.522750] [drm] qxl: 63M of IO pages memory ready (VRAM domain) [ 0.522750] [drm] qxl: 32M of Surface memory size [ 0.650714] fbcon: qxldrmfb (fb0) is primary device [ 0.668487] qxl 0000:00:02.0: fb0: qxldrmfb frame buffer device # dmesg 可列出核心产生的讯息, 包括硬件侦测的流程也会显示出来 # 透过 grep 来 qxl 虚拟卡的相关信息，可发现如上信息 范例二：承上题，要将捉到的关键词显色，且加上行号来表示 [aweip@Manjaro ~]$ dmesg | grep -n --color=auto 'qxl' 515:[ 0.522749] [drm] qxl: 16M of VRAM memory size 516:[ 0.522750] [drm] qxl: 63M of IO pages memory ready (VRAM domain) 517:[ 0.522750] [drm] qxl: 32M of Surface memory size 529:[ 0.650714] fbcon: qxldrmfb (fb0) is primary device 539:[ 0.668487] qxl 0000:00:02.0: fb0: qxldrmfb frame buffer device # 除了 qxl 会有特殊颜色来表示之外，最前面还有行号, 其实颜色显示已经是默认在 alias 当中了 范例三：承上题，在关键词所在行的前两行与后三行也一起捉出来显示 [aweip@Manjaro ~]$ dmesg | grep -n -A3 -B2 --color=auto 'qxl' # 关键词之前与之后的数行也被显示出来, 这样可以将关键词前后数据提出来进行分析 基础正则表达式练习 例题一 : 搜寻特定字符串 [aweip@Manjaro ~]$ grep -n 'the' regular_express.txt # 寻找包含 test 这一字符的行 [aweip@Manjaro ~]$ grep -vn 'the' regular_express.txt # 列出不包含 the 的行 例题二 : 利用中括号 [] 来搜寻集合字符 [aweip@Manjaro ~]$ grep -n 't[ae]st' regular_express.txt # 寻找包含 tast 或 test 这一类字符的行 [aweip@Manjaro ~]$ grep -n '[^g]oo' regular_express.txt # 反向选择 [^]，寻找 oo 前面不是 g 的字符 [aweip@Manjaro ~]$ grep -n '[^a-z]oo' regular_express.txt # [^a-z]，寻找 oo 前面不是小写字母的字符 [aweip@Manjaro ~]$ grep -n '[a-zA-Z0-9]' regular_express.txt # 取得有数字大小写字母的行 [aweip@Manjaro ~]$ grep -n '[^[:lower:]]oo' regular_express.txt [aweip@Manjaro ~]$ grep -n '[[:digit:]]' regular_express.txt # 考虑到语系对于编码顺序的影响，可以直接使用特殊符号，[:lower:] 代表的就是 a-z 的意思 例题三 ：行首与行尾字符 ^ $ [aweip@Manjaro ~]$ grep -n '^the' regular_express.txt # 取得 the 只在行首列出的行 [aweip@Manjaro ~]$ grep -n '^[a-z]' regular_express.txt # 取得行首列为小写字母的行 [aweip@Manjaro ~]$ grep -n '\.$' regular_express.txt # 取得行尾结束为小数点 (.) 的那一行 例题四 ： 任意一个字符 . 与重复字符 * . (小数点)：代表『一定有一个任意字符』的意思； * (星星号)：代表『重复前一个字符， 0 到无穷多次』的意思，为组合形态 [aweip@Manjaro ~]$ grep -n 'g..d' regular_express.txt # 找到有 g_ _d 样式的长度为 四 的字符的行 [aweip@Manjaro ~]$ grep -n 'ooo*' regular_express.txt # 找到需要≥2个 o 以上的字符串，第一个 oo 肯定必须要存在，第二个 o 则是可有可无的多个 o [aweip@Manjaro ~]$ grep -n 'g.*g' regular_express.txt # 『.*』代表零个或多个任意字符 例题五 : 限定连续 RE 字符范围 {} [aweip@Manjaro ~]$ grep -n 'o\{2\}' regular_express.txt # 因为 { 与 } 的符号在 shell 是有特殊意义的，因此必须要使用跳脱字符 \ 来让其失去特殊意义 # 限制一个范围区间内的重复字符数为2，即要找到两个 o 的字符串 [aweip@Manjaro ~]$ grep -n 'go\{2,5\}g' regular_express.txt # 找出 g 后面接 2 到 5 个 o ，然后再接一个 g 的字符串 基础正则表达式字符汇整 (characters) RE 字符 意义与范例 ^word 意义：待搜寻的字符串(word)在行首！ 范例：搜寻行首为 # 开始的那一行，并列出行号 grep -n '^#' regular_express.txt word$ 意义：待搜寻的字符串(word)在行尾！ 范例：将行尾为 ! 的那一行打印出来，并列出行号 grep -n '!$' regular_express.txt . 意义：代表『一定有一个任意字符』的字符！ 范例：搜寻的字符串可以是 (eve) (eae) (eee) (e e)， 但不能仅有 (ee) ！亦即 e 与 e 中间『一定』仅有一个字符，而空格符也是字符！ grep -n 'e.e' regular_express.txt \ 意义：跳脱字符，将特殊符号的特殊意义去除！ 范例：搜寻含有单引号 ' 的那一行！ grep -n \' regular_express.txt * 意义：重复零个到无穷多个的前一个 RE 字符 范例：找出含有 (es) (ess) (esss) 等等的字符串，注意，因为 可以是 0 个，所以 es 也 是符合带搜寻字符串。另外，因为 为重复『前一个 RE 字符』的符号， 因此，在* 之前必须 要紧接着一个 RE 字符喔！例如任意字符则为 『.』 ！ grep -n 'ess' regular_express.txt [list] 意义：字符集合的 RE 字符，里面列出想要撷取的字符！ 范例：搜寻含有 (gl) 或 (gd) 的那一行，需要特别留意的是，在 [] 当中『谨代表一个待搜寻 的字符』， 例如『 a[afl]y 』代表搜寻的字符串可以是 aay, afy, aly 即 [afl] 代表 a 或 f 或 l 的意思！ grep -n 'g[ld]' regular_express.txt [n1-n2] 意义：字符集合的 RE 字符，里面列出想要撷取的字符范围！ 范例：搜寻含有任意数字的那一行！需特别留意，在字符集合 [] 中的减号 - 是有特殊意义的， 他代表两个字符之间的所有连续字符！但这个连续与否与 ASCII 编码有关，因此，你的编码需要 设定正确(在 bash 当中，需要确定 LANG 与 LANGUAGE 的变量是否正确！ ) 例如所有大写字 符则为 [A-Z] grep -n '[A-Z]' regular_express.txt [^list] 意义：字符集合的 RE 字符，里面列出不要的字符串或范围！ 范例：搜寻的字符串可以是 (oog) (ood) 但不能是 (oot) ，那个 ^ 在 [] 内时，代表的意义是『反向选择』的意思。 例如，我不要大写字符，则为 [^A-Z]。但是，需要特别注意的是， 如果以 grep -n [^A-Z] regular_express.txt 来搜寻，却发现该文件内的所有行都被列 出，为什么？因为这个 [^A-Z] 是『非大写字符』的意思， 因为每一行均有非大写字符，例如第 一行的 "Open Source" 就有 p,e,n,o.... 等等的小写字 grep -n 'oo[^t]' regular_express.txt {n,m} 意义：连续 n 到 m 个的『前一个 RE 字符』 意义：若为 {n} 则是连续 n 个的前一个 RE 字符， 意义：若是 {n,} 则是连续 n 个以上的前一个 RE 字符！ 范例：在 g 与 g 之间有 2 个到 3 个的 o 存在的字符串，亦即 (goog)(gooog) grep -n 'go{2,3}g' regular_express.txt Linux三剑客之二 —— sed sed 工具 [aweip@Manjaro ~]$ sed [-nefr] [动作] -n ：使用安静(silent)模式。在一般 sed 的用法中，所有来自 STDIN 的数据一般都会被列出到屏幕上。但如果加上 -n 参数后， 则只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。 -e ：直接在指令列模式上进行 sed 的动作编辑； -f ：直接将 sed 的动作写在一个文件内， -f filename 则可以执行 filename 内的 sed 动作； -r ： sed 的动作支持的是延伸型正则表达式的语法。 (预设是基础正则表达式语法) -i ：直接修改读取的文件内容，而不是由屏幕输出。 动作说明： [n1,n2]function n1, n2 ：不见得会存在，一般代表『 选择进行动作的行数』， 举例来说，如果我的动作 是需要在 10 到 20 行之间进行的， 则10,20/[动作行为] a ：新增append， a 的后面可以接字符串，而这些字符串会在目前的下一行出现 c ：取代， c 的后面可以接字符串，这些字符串可以取代 n1,n2 之间的行 i ：插入， i 的后面可以接字符串，而这些字符串会在新的一行出现(目前的上一行) d ：删除，因为是删除，所以 d 后面通常不接任何字符 p ：打印，亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运作 s ：取代，可以直接进行取代的工作，通常这个 s 的动作可以搭配正则表达式，例如 1,20s/old/new/g 就是 以行为单位的新增/删除功能 范例一： 将 /etc/passwd 的内容列出并且打印行号，同时， 请将第 2~5 行删除！ [aweip@Manjaro ~]$ nl /etc/passwd | sed '2,5d' # sed 的动作为 '2,5d' ， d 就是删除,2,5即删除 2-5 行 # sed 后面接的动作，请务必以 '' 两个单引号括住 [aweip@Manjaro ~]$ nl /etc/passwd | sed '3,$d' # 删除第 3 到最后一行，钱字号『 $ 』代表最后一行 范例二：承上题，在第二行后(亦即是加在第三行)加上『 drink tea?』字样 [aweip@Manjaro ~]$ nl /etc/passwd | sed '2a drink tea' # a(append),在第二行后添加，要在第二行前则将『 a 』变成『 i 』即可 [aweip@Manjaro ~]$ nl /etc/passwd | sed '2a Drink tea or ......\ > drink beer ?' # 新增不只一行,但是每一行之间都必须要以反斜杠『 \ 』来进行新行的增加 以行为单位的取代与显示功能 范例三： 将第 2-5 行的内容取代成为『No 2-5 number』 [aweip@Manjaro ~]$ nl /etc/passwd | sed '2,5c No 2-5 number # '_,_c 内容' 范例四： 仅列出 /etc/passwd 文件内的第 5-7 行 [aweip@Manjaro ~]$ nl /etc/passwd | sed -n '5,7p' # -n 代表的是『安静模式』 部分数据的搜寻并取代的功能 sed 's/要被取代的字符串/新的字符串/g' 范例五： sed与正则表达式配合练习 步骤一：先使用 grep 将关键词 MAN 所在行取出 [aweip@Manjaro ~]$ cat /etc/man_db.conf | grep 'MAN' # MANDATORY_MANPATH manpath_element # MANPATH_MAP path_element manpath_element # MANDB_MAP global_manpath [relative_catpath] # every automatically generated MANPATH includes these fields 步骤二： 删除掉批注之后的数据 [aweip@Manjaro ~]$ cat /etc/man_db.conf | grep 'MAN'| sed 's/#.*$//g MANDATORY_MANPATH /usr/man # ...省略 # 从上面可以看出来，原本批注的数据都变成空白行啦！所以，接下来要删除掉空白行 [aweip@Manjaro ~]$ cat /etc/man_db.conf | grep 'MAN'| sed 's/#.*$//g' | sed '/^$/d' MANDATORY_MANPATH /usr/man MANDATORY_MANPATH /usr/share/man MANDATORY_MANPATH /usr/local/share/man 直接修改文件内容(危险动作) 范例六：利用 sed 将 regular_express.txt 内每一行结尾若为 . 则换成 ! [aweip@Manjaro ~]$ sed -i 's/\.$/\!/g' regular_express.txt # 上头的 -i 选项可以让你的 sed 直接去修改后面接的文件内容而不是由屏幕输出喔！ # 这个范例是用在取代！ 请您自行 cat 该文件去查阅结果啰！ 范例七：利用 sed 直接在 regular_express.txt 最后一行加入『# This is a test』 [aweip@Manjaro ~]$ sed -i '$a # This is a test' regular_express.txt # 由于 $ 代表的是最后一行，而 a 的动作是新增，因此该文件最后新增 延伸正则表达式 基础的就基本扎布多德勒 文件的格式化与相关处理 格式化打印： printf [dmtsai@study ~]$ printf '打印格式' 实际内容 \a 警告声音输出 \b 退格键(backspace) \f 清除屏幕 (form feed) \n 输出新的一行 \r 亦即 Enter 按键 \t 水平的 [tab] 按键 \v 垂直的 [tab] 按键 \xNN NN 为两位数的数字，可以转换数字成为字符 范例一： 将数据的文件 (printf.txt) 内容仅列出姓名与成绩： (用 [tab] 分隔) [dmtsai@study ~]$ printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat printf.txt) Name Chinese English Math Average DmTsai 80 60 92 77.33 VBird 75 55 80 70.00 Ken 60 90 70 73.33 范例二： 将上述资料关于第二行以后，分别以字符串、整数、小数点来显示 [dmtsai@study ~]$ printf '%10s %5i %5i %5i %8.2f \n' $(cat printf.txt | grep -v Name) DmTsai 80 60 92 77.33 VBird 75 55 80 70.00 Ken 60 90 70 73.33 范例三：列出 16 进位数值 45 代表的字符 [dmtsai@study ~]$ printf '\x45\n' E Linux三剑客之三——awk awk：好用的数据处理工具 , awk 主要是处理『每一行的字段内的数据』，而默认的『字段的分隔符为 "空格键" 或 "[tab]键" 』 [dmtsai@study ~]$ awk '条件类型 1{动作 1} 条件类型 2{动作 2} ...' filename 举例 [dmtsai@study ~]$ last -n 5 <==仅取出前五行 dmtsai pts/0 192.168.1.100 Tue Jul 14 17:32 still logged in dmtsai pts/0 192.168.1.100 Thu Jul 9 23:36 - 02:58 (03:22) dmtsai pts/0 192.168.1.100 Thu Jul 9 17:23 - 23:36 (06:12) dmtsai pts/0 192.168.1.100 Thu Jul 9 08:02 - 08:17 (00:14) dmtsai tty1 Fri May 29 11:55 - 12:11 (00:15) # 取出账号与登入者的 IP ，且账号与 IP 之间以 [tab] 隔开 [dmtsai@study ~]$ last -n 5 | awk '{print $1 "\t" $3}' dmtsai 192.168.1.100 dmtsai 192.168.1.100 dmtsai 192.168.1.100 dmtsai 192.168.1.100 dmtsai Fri awk 后续的所有动作是以单引号『 ' 』括住的 awk 的内建变量 变量名称 代表意义 NF 每一行 ($0) 拥有的字段总数 NR 目前 awk 所处理的是『第几行』数据 FS 目前的分隔字符，默认是空格键 awk 的逻辑运算字符 算单元 代表意义 > 大于 < 小于 >= 大于或等于 <= 小于或等于 == 等于 != 不等于
总结一下这十天我干了个啥 C++与OOP基础->参考书籍：《C++ Primer Plus》，练手项目：基于多态实现的公司管理系统（小白白白白难度）； Linux学习->参考书籍：《鸟哥的LINUX私房菜》，练手项目：阅读linux0.11源码; 感想：啊啊啊啊心态实在太摆了，感觉这些天很多只是应付式地学习，相比于期末那效率实在不太够看，但两本厚书也是囫囵吞枣地看着。 后续安排 Unix网络编程； Leetcode； Qt(如果有可能的话);
契机 说来，其实这并不算是我的第一个博客 不久前在腾讯云白嫖过一个三十天试用的轻量应用云服务器，根据B站UP CodeSheep 的一个视频简易地建立了一个博客，然后就......过期寄掉了。 为什么想要搞这个呢，其实是这学期的专业核心课，让我重拾了对于整活的热情，主要是归咎于这学期我的生活习惯和态度开始有了很大的改变，很感谢这半年遇到的令我开心的人和事——谢GG，嘉烽，书记，XMGG，寄寄......还有我们之间的那些回忆。这一切的一切让走在过去步履沉重的我，慢慢地踏出了那些曾在心头缠绕的阴霾。量变引起质变，时隔多年，我再一次感受到了头脑中的那种明朗与舒畅，因为我似乎有了自己的清晰目标和规划（虽然未来还是不明朗就是了）。生活美好而有限，我们应当好好对待。 搭建过程 写在开始 在书记的影响下，我在搭建博客时选择了采用Typecho博客系统，顺手找了个看着顺眼且免费的主题 Viosey，handsome主题虽然好看，但钱包羞涩还是选择了放弃。说实话，在宝塔面板的搭建的过程十分简易，但为了水一篇文章，还是写写来加深一下印象。 前期准备 服务器：腾讯云轻量应用服务器2核4G6M 系统：Debian 11.1 64bit 图床：七牛云对象储存服务 SSH工具：MobaXterm 22.0 安装宝塔面板 1.打开腾讯云控制台，为宝塔面板开放8888端口； 2.打开MobaXterm的ssh界面，Debian 11下一行指令即可安装: ​wget -O install.sh http:``//download.bt.cn/install/install-ubuntu_6.0.sh && bash install.sh 等待安装成功后会出现宝塔后台登陆地址，账号，密码。打开网址，输入提供的信息以登录； 3.配置选择 在此我选择了LNMP配置（ Ngnix 1.18 + MySQL 5.7 + Pure-Ftpd 1.0.49 + PHP 7.4 + phpMyAdmin 4.0 ），我择安装后等待，后输入ip地址:80，打开网页看见Ngnix欢迎界面确认安装成功，PHP安装也可以通过在/www/wwwroot/www.域名.com/ 文件夹内建立test.php测试是否成功。 4.具体设置 打开宝塔面板面板设置，根据所需进行设置，在网站界面添加站点，按实际情况添加域名，设置数据库。 安装Typecho 本地下载Typecho文件压缩包，解压到本地； 通过FTP上传至建立的/www/wwwroot/www.域名.com/ 文件夹内； 输入ip地址:80，进入Typecho安装界面，按提示完成安装。 在这一步我遇到了安装报错，情形如下： 解决方式：在/usr目录下创建uploads 文件夹，权限设置为755 安装主题 选择一个自己喜欢的主题，本地解压（上传再解压也行），将主题文件夹放置在网站目录的usr/themes/目录下 尾声 第一篇博客水完啦，如题而言，本学期后半段是我这个阶段新的起点。希望在日后，跑步锻炼，学习Linux，C++，数据结构与算法，CSS+HTML5，一切都能按计划顺利推行下去。