跳转至

linux 相关-基本命令

linux 相关

linux 命令 option 通用格式

  • POSIX-styled 的 option 由一个 dash 和一个字符组成
  • GNU-style 的 long option 由两个 dash 和一个关键字 (keyword) 组成
    • 关键字能被缩写,只要足够区分不同关键字
    • 如果关键字需要一个参数 (argument),可以在关键字后紧跟一个等号=,然后紧跟着关键字的值。或者将关键字和值用空白字符 (whitespace) 分隔开。
    • 如果关键字被多次赋值,则以最后一次的为准

man wget

  • 解析方法
    • GUN getopt
  • 是否支持合并
  • 是否支持选项放在参数后面
  • --表示 option 结束。Since the options can be specified after the arguments, you may terminate them with --. So the following will try to download URL -x, reporting failure to log: wget -o log -- -x

vim

Vim Cheat Sheet (rtorr.com)

基本

# insert mode
i, o, O

# 光标移动
i, j, k, l
gg, G
w, W, b, B # move word

# 复制粘贴
yy, p
dw # 剪切单词

/pattern   # 查找
n

添加 tab

  • ctrl-v 进入 visual block 模式(如果使用 windows terminal,ctrl-v 被设置为粘贴会导致无法进入),或者 shift-v 进入 visual line 模式。
  • "shift + dot",被选中的行便会 tab 一次,重复"dot"可以 tab 任意次
    • 或者:进入命令模式,>往右 tab,<往左 tab

也可以直接使用命令模式,以下命令将 1-5 行向右 tab 2 次

:1,5>>

高级

光标移动

H, M, L #  top, middle, bottom of screen

fx # jump to next occurrence of character x
} # jump to next paragraph (or function/block, when editing code)
{

zz # center cursor on screen

Ctrl + b - move back one full screen
Ctrl + f - move forward one full screen
Ctrl + d - move forward 1/2 a screen
Ctrl + u - move back 1/2 a screen

查找替换

  • %表示整个文件 range(否则只会替换第一次匹配)
:%s/xxx/yyy/g

执行 shell 命令

:!{cmd}

:!ls -alh # 查看当前目录下文件

:w !{cmd}   # buffer | cmd

:%!{cmd}   # buffer | cmd | buffer
:%!grep xxx  # 过滤文件内容,保留匹配的部分

忘记 sudo

write with sudoHow does the vim "write with sudo" trick work? - Stack Overflow

:w !sudo tee %
  • w 命令完整格式::[range]w[rite] [++opt] !{cmd}
    • 表示执行 cmd,并将当前编辑缓冲区内容作为 cmd 输入
    • 例子:w !grep xxx,grep 文件内容
  • %:这里表示文件名
  • 因此上述命令将 buffer 内容 pipe 给 sudo 执行的 tee 命令,tee 命令将 stdin 输出到当前文件和 stdout,从而实现对文件的写入。

为上述命令设置别名 w!!

" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %

编辑二进制文件

binary file - How can I use Vim as a hex editor? - Vi and Vim Stack Exchange

:%!xxd

  • :%!{cmd}有点像 loopback,把当前缓冲区 pipe 给 cmd 然后再将其输出写回到缓冲区。
  • xxd 输入二进制输出 hex 文本

:%!xxd -r

  • xxd -r 输入 hex 文本输出二进制

:wq 写回文件

配置文件

map <C-c> "+y<CR>
map <C-v> "+p<CR>

command! Vb normal! <C-v>

cmap w!! w !sudo tee > /dev/null %

自定义命令:key bindings - Is there a command to enter Visual Block mode? - Vi and Vim Stack Exchange

cp 注意点

  • cp file1 file2 ... dir
  • cp -r dir1 dir2
    • 如果 dir2 存在,则将 dir1 复制到 dir2 内,即 dir2/dir1
    • 如果 dir2 不存在,则将 dir1 复制为 dir2
  • cp dir1/* dir2
    • 将 dir1 下所有文件复制到 dir2 内,如果 dir1 存在目录,则应添加-r 选项

sed, awk, grep

这些命令要深入研究的话,内容都很多。比如 awk 可以算是一种用于处理文本的解释型编程语言。因此,比较好的方法是从需求出发,看看在 linux 下一般有哪些文字处理的需求,再看使用哪种工具比较方便简单。

命令格式

grep [option] pattern file

sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)

awk [options] 'pattern {action}' [file]

正则表达式

基本正则表达式(Basic Regular Expressions)和扩展正则表达式(Extended Regular Expressions)是两种 POSIX 正则表达式风格。

BRE 可能是如今最老的正则风格了,对于部分特殊字符(如 +, ?, |, {)需要加上转义符 \ 才能表达其特殊含义。

ERE 与如今的现代正则风格较为一致,相比 BRE,上述特殊字符默认发挥特殊作用,加上 \ 之后表达普通含义。

sed

  • 修改文件中某部分内容。一般可以使用正则表达式,匹配到对应位置,然后进行修改。

    //将文件中所有的 key=xxx,修改为 key=${val}
    //-i 表示在原文件上修改,去掉后会将结果输出到命令行
    // 这里还用到了字符串拼接语法,将两个字符串写到一起就会拼接。单引号内不能进行转义,因此为了使用变量 val 需要使用双引号。
    sed -i 's/key=[0-9]+/'"key=${val}/g"
    

    sed 其它命令: - s 替换 - d 删除 - c\text :选定行改成新文本text - 在实际使用中,如果新文本需要跨多行,每一行的末尾(除了最后一行)通常需要加上反斜线(\) - a 当前行下插入文本 - i 当前行上插入文本

    //找到某一行,然后整行替换
    sed -i "/config_pio_local_num_iotasks/ c\config_pio_local_num_iotasks = 3"
    

地址范围匹配模式

sed /xxx/,/yyy/{ commands }

  • 这里使用了 here document
  • bash -s 才可以指令这样的多行脚本
ssh $REMOTE "bash -s" <<EOF
sed -i "/$WG_PUB_KEY/,/^config/{
    s/option endpoint_port.*/option endpoint_port '$PUBLIC_PORT'/
    s/option endpoint_host.*/option endpoint_host '$PUBLIC_IP'/
}" "/etc/config/network"

#wg set $WG_IF peer $WG_PUB_KEY endpoint $PUBLIC_IP:$PUBLIC_PORT

ifconfig $WG_IF down && ifup $WG_IF
EOF

多行命令

sed -i -e '/^port/c #port: 7890' -e '/^socks-port/c #socks-port: 7891' -e 's/^allow-lan.*/allow-lan: true/' -e '/^allow-lan/i mixed-port: 11223' glados.yaml

更多例子

sed -i '$a\\n' /tmp/grub.new # 文件最后一行添加一行换行
  • $表示最后一行
  • a表示在指定行后面添加内容
sed -i ''${INSERTGRUB}'r /tmp/grub.new' $GRUBDIR/$GRUBFILE
  • r /tmp/grub.new:读取文件内容并插入指定行后

awk

awk -F'TXT' '{print $NF}' |xargs  # TXT为分隔符,$NF为最后一列,xargs去除空格(strip

其它

head, tail

tail         # 输出最后10行
tail -n k    # 输出最后k行
tail -n +k   # 输出从第k行(1开始)的所有行

head         # 输出前10行
head -n k    # 输出前k行
head -n -k   # 输出除结尾k行后的所有行

xargs

xargs [options] [command [initial-arguments]]

从标准输入读取 items(使用 blank 或者 newline 分隔),然后执行 command(默认/bin/echo)。使用 -n 决定每次传递多少 iterm。-p 可以看到执行的具体命令,并决定是否执行。

➜  ~ echo 1 2 3 4 5 6 7 8 9 | xargs -n 3 -p
echo 1 2 3?...

iterm 会接在 command 结尾,如果想要指定位置,需要指定 replace str -I{}

l "/mnt/Disk2/BT/downloads/Video/TV_anime/" | grep Juju | cut -d ' ' -f 9- | xargs -I {} rm -r "/mnt/Disk2/BT/downloads/Video/TV_anime/{}"

不过 -I 隐含了 -L 1,因此输入会按照换行分隔,并且一次输入一行。(xargs 并不支持多个 replace str)

--delimiter=delim, -d delim:指定输入的分隔符,单个字符,可以是 C 风格的字符,如转移字符,字符八进制表示等。

tar

archive - How do I tar a directory of files and folders without including the directory itself? - Stack Overflow

tar czf xxx.tar.gz -C <dir> .
  • -C : change the current directory
  • .: add the entire current directory

cut

for IPV6_SUBNET in $NET_IPV6_SUBNETS; do
SRC=$(echo $IPV6_SUBNET | cut -d "/" -f 1)"/128"
...
done

grep

  • -o: only print matched part
iAddr=`ip addr show dev $interface |grep "inet.*" |head -n1 |grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\/[0-9]\{1,2\}'`

查找一个目录中的所有文件

grep -r "your_string" /path/to/directory

coreutils

env

run command in a modifed environment

env invocation (GNU Coreutils 9.5)

  • -i
    • -
    • --ignore-environment
    • Start with an empty environment, ignoring the inherited environment.
env -i PATH="$PATH" foo  # 除了 PATH,以空白 env 运行 foo 程序。
env - PATH="$PATH" foo  # 简略形式
  • -C
    • --chdir=dir
    • Change the working directory to dir before invoking command.
env --chdir=/build make

另外的作用就是,用于脚本文件第一行,用于找到执行文件执行

When a script’s interpreter is in a non-standard location in the PATH environment variable, it is recommended to use env on the first line of the script to find the executable and run it:

#!/bin/sh
#!/usr/bin/python3

#!/usr/bin/env bash
#!/usr/bin/env python3