Unique's Blog

missing-semester

2021-06-09 · 2027字 · 9 min read
🏷️  Linux

总结 missing-semester 的内容,包括 shell,git,vim...
<! -- more -->

shell

文件和目录的权限

权限 文件 目录
r 可以读取文件内容 可查看列举目录中的文件(dir name),只涉及目录文件
w 可以修改文件内容 可以创建、删除或重命名目录中的文件
x 可以将文件作为程序运行 可以进入该目录访问目录中的文件信息(包括文件元数据)

需要注意的是 ls 命令需要进入目录并访问其中的文件,所以需要目录的 x 权限。

  • cat d1/file1: 需要 d1 的 x 权限,file1 的 r 权限
  • touch file2: 需要当前目录的 x 权限(访问该文件)
    • 如果文件不存在,需要目录的 w 权限
    • 如果文件已经存在,还需要该文件的 w 权限(修改访问时间)

pipeline

  • ls -l . | tail -n2 > ls.txt
  • curl --head google.com | grep -i content-length | cut -d ' ' -f 2

sudo

作用:临时获取超级用户权限,执行单个命令。只对指定的命令生效,不切换用户会话。
sudo su 通过 sudo 提升权限后进入 root 会话(su 默认切换到 root 会话)

通配符

shell 中支持的通配符:

  • *:通配符,匹配零个或多个字符,*.txt
  • ?:通配符,匹配任意单个字符,file?
  • []:匹配指定范围或指定集合中的任意单个字符(需要目录中有匹配的文件),file[1-3]
  • {}大括号扩展,构造字符串列表或生成序列,即使文件不存在,也会生成字符串。支持嵌套扩展以及范围表达式 {1..9}、{a..f},file{aa,bb}.txt
  • \:转义字符
echo file{A,B}{1,2}.txt
fileA1.txt fileA2.txt fileB1.txt fileB2.txt # 笛卡尔积

在 shell 中,如果命令中含有通配符,Tab 后自动完成扩展(对于变量也可以完成扩展)。(执行命令时,会对这些通配符进行扩展 expansion)

常用的特殊值

  • $0: 脚本名称
  • $1, $2...: 传递给脚本或函数的第 1、2... 个参数
  • $#:位置参数的个数
  • $*:所有位置参数,以一个整体字符串的形式表示
  • $@:所有位置参数,以独立的字符串形式表示
  • $$:运行当前脚本的 Shell 进程 ID
  • $?: 上一条命令的退出码,范围是 0-255,通常使用 0 表示没有错误。可以使用 exit 指定退出码。
  • 特殊字符 https://tldp.org/LDP/abs/html/special-chars.html

没有使用双引号,$*$@ 的效果是一样的。它们都会将所有参数拼接成一个长字符串,并按空格分隔。
"$*""$@" 放在双引号中时,行为就有所不同。"$*" 会将所有的参数合并成一个单一的字符串,参数之间由空格分隔;"$@" 会将每个参数保持为独立的字符串,输出时每个参数被正确地保留为原样,常用于参数的循环遍历场景。

分组命令

在 Shell 中,分号 ; 是一种命令分隔符,用于在一行中依次执行多条命令。
分号可以用于分组命令组合(用括号 () 或大括号 {})。

  • 括号分组:创建子 Shell 执行
    所有命令会在一个子 Shell 中执行。(command1; command2; command3)
  • 大括号分组:在当前 Shell 中执行
    需要用分号或换行符结束最后一条命令。{ command1; command2; command3; }

命令替换

命令替换是将一个命令的输出结果作为另一个命令的参数。

echo "当前目录文件数量:$(echo $(ls | wc -l))"

$(command) 包裹命令,支持嵌套。
默认情况下,命令替换只捕获标准输出(stdout)。如果需要捕获错误信息(stderr),可以使用 2>&1 :

output=$(ls non_existent_file 2>&1)
if [ $? -ne 0 ]; then
    echo "命令执行失败:$output"
fi

进程替换

进程替换(Process Substitution)用于将进程的输出或输入映射为一个文件名(临时文件),需要将命令结果传递给需要文件名参数的工具时非常有用。

# 将命令的结果输出到一个临时文件中,并将 <(command) 替换成临时文件名
<(command)  # 将命令的 输出 映射为一个文件名(供读取)=> /dev/fd/NUM

# 创建一个临时文件,并将 >(command) 替换成临时文件名
# 任何写入该文件的内容都会被发送到 command 的标准输入
>(command)  # 将命令的 输入 映射为一个文件名(供写入)

主要用于一些需要接受文件名作为参数的命令:

diff <(ls dir1) <(ls dir2) # ls dir1 和 ls dir2 的输出分别被当作文件名传递给 diff
grep "pattern" <(echo -e "line1\nline2\npattern")
cat <(echo "Config Line 1") <(echo "Config Line 2") # 合并文件

cat file | tee >(grep "pattern" > matched.txt) >(wc -l > line_count.txt) # 分流,一个保存匹配的行,一个统计行数

数值计算

整数计算:使用 $(( ... ))

a=5
b=3
result=$((a + b))   # 加法
echo "Result: $result"  # 输出: 8

其中如果使用变量,可以不加 $。

浮点计算:使用 bc 计算(必须先安装)

a=5.5
b=2.3
result=$(echo "$a + $b" | bc)
echo "Result: $result"  # 输出: 7.8

echo "scale=2; 10/3" | bc # 浮点运算,使用 scale 指定小数位数, 2位小数
echo "obase=2; 9" | bc    # 十进制转二进制
echo "ibase=2; 1010" | bc # 二进制转十进制
echo "obase=2; ibase=16; 1F" | bc 
# 注意:如果需要同时指定,先指定 obase (因为ibase 会影响后面所有的数字的解析,包括 obase 值)
# 16 进制的字母使用大写

使用 python 计算

python -c "x = 10; y = 5; print(x * y)"       # 可以结合 shell 变量
python -c "import math; print(math.sqrt(16))" # import

shebang

在 shell 中与其他语言的脚步交互,在脚本首行定义 shebang 指定解释器,使用环境变量更加通用 #!/usr/bin/env python

#!/usr/bin/env python
import sys
for arg in reversed(sys.argv[1:]):
    print(arg)

tools 命令

  • man / tldr
    使用 man 或者 tldr(提供使用示例)学习命令的使用
  • convert / ffmpeg
    图片、视频处理工具
  • find / fd
    文件目录查找,fd 默认使用正则
  • grep / ag
    文件内容查找,文件名查找等
  • tree / broot
    目录浏览
grep -C 5 "pattern" file.txt # 输出匹配结果前后五行
# -i 忽略大小写
# -n 显示行号
# -l 只显示包含匹配的文件名
# -v 反向匹配
# -E 使用扩展正则表达式(等同于 egrep)
# -R 递归搜索文件夹内所有文件, --exclude= 排除文件, --exclude-dir= 排除目录

# -G 在匹配的文件中搜索内容
ag -C 5 foo  # 文件中包含 foo 的行,以及前后5行内容
# grep -C 5 "foo" filename

ag -i foo -G bar # 文件名含有 bar 的文件,内容含有 foo 的行,忽略大小写
# grep -i "foo" $(find . -type f -name "*bar*")

ag "^#\!" -G "sh$" --files-without-match # 没有匹配到的 sh 文件名
# grep -L "^#\!" $(find . -type f -name "*.sh")
# find . -type f -name "*.sh" | xargs grep -L "^#\!"

基础语法

  • 同一行的多个命令可以用 ; 分隔。程序 true 的返回码永远是 0,false 的返回码永远是 1。
基础语法
#!/bin/bash

# 变量定义
name="World"
count=5

# 输出文本
echo "Hello, $name!"

# 条件判断
if [[ $count -gt 0 ]]; then
    echo "Counting down..."
    for ((i = $count; i > 0; i--)); do
        echo "i = $i"
    done
else
    echo "Count must be greater than 0"
fi

# 函数定义
greet() {
    echo "Goodbye, $1!"
}

# 调用函数
greet "User"

# 文件操作
file="test.txt"
if [[ -f "$file" ]]; then
    echo "File $file exists."
else
    echo "File $file does not exist."
    echo "Creating file $file..."
    touch "$file"
fi

# 获取命令行参数
echo "Script name: $0"     # 脚本名称
echo "First argument: $1"  # 第一个参数
echo "Second argument: $2" # 第二个参数

# 命令替换
date_today=$(date)
echo "Today's date is: $date_today"

# 退出脚本
exit 0

本文链接: missing-semester

版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

发布日期: 2021-06-09

最新构建: 2024-12-26

本文已被阅读 0 次,该数据仅供参考

欢迎任何与文章内容相关并保持尊重的评论😊 !

共 43 篇文章 | Powered by Gridea | RSS
©2020-2024 Nuo. All rights reserved.