跳转至

bash

bash

参考

Bash Reference Manual: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html

rediction

Redirections (Bash Reference Manual) (gnu.org) 每个程序有一个打开文件表,记录文件描述符 fd 和对应的文件 vnode

  • 0: stdinput
  • 1: stdout
  • 2: stderr

重定向就是修改其中的项

  • 重定向到文件(新建文件,或者 truncte 已有文件)
  • duplicate,复制已有的项
n>file  # 重定向输出n,n默认为1
n<file  # 重定向输入n,n默认为0

&>file  # 重定向stdout和stderr

n>>file # 重定向输出n,append到文件
&>>file # 重定向stdout和stderr,append到文件

n>&m    # 复制文件描述符

重定向顺序很重要

  • 第一行命令,先将 stdout 重定向为文件,然后用 stdout 项覆盖 stderr 项,因此二者都指向文件
  • stderr 先被重定向到 stdout,然后把 stdout 重定向到文件。因此 stderr 还是会输出到屏幕上
ls > dirlist 2>&1  # stdout和stderr被重定向到文件
ls 2>&1 > dirlist  # stderr仍会输出在屏幕

ls 2>dirlist >&2   # 是否可行?   实验确实可行

特殊的重定向文件:网络

zsh 不支持

bash - /dev/tcp not found - Unix & Linux Stack Exchange

printf "GET / HTTP/1.1\n\n" > /dev/tcp/74.125.225.19/80

Redirections (Bash Reference Manual) (gnu.org) /dev/tcp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, Bash attempts to open the corresponding TCP socket. /dev/udp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, Bash attempts to open the corresponding UDP socket.

其它

here-document

[n]<<[-]word
        here-document
delimiter

here-string

[n]<<< word

Moving File Descriptors

[n]<&digit-
[n]>&digit-  # 重定向后,关闭digit

Opening File Descriptors for Reading and Writing

causes the file whose name is the expansion of word to be opened for both reading and writing on file descriptor n

[n]<>word

expansion(扩展)

扩展 = 替换 = 展开

扩展即将一个变量展开,得到实际的值。用于变量定义、命令替换等地方。

变量扩展

bash 手册中将变量称为 shell parameter

  • 未定义时替换
  • 定义时替换 用途
PATH="${PATH:+${PATH}:}/staff/fyyuan/.fzf/bin"
  • 子字符串替换

${parameter: offset} ${parameter: offset: length}

This is referred to as Substring Expansion. It expands to up to length characters of the value of parameter starting at the character specified by offset.

$ string=01234567890abcdefgh
$ echo ${string:7}
7890abcdefgh
$ echo ${string:7:0}

$ echo ${string:7:2}
78
$ echo ${string:7:-2}
7890abcdef
$ echo ${string: -7}
bcdefgh
$ echo ${string: -7:0}

$ echo ${string: -7:2}
bc
$ echo ${string: -7:-2}
bcdef

命令替换 (扩展)

两种格式

VAR=$(cat file1.txt nofile.txt 2>&1)
echo $VAR

`command`

命令替换就是将一个命令的结果(输出,默认为 stdout)替换到当前位置,比如给变量赋值,或者嵌入字符串中。

Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.

获得命令输出,换行消失问题

How to avoid bash command substitution to remove the newline character? - Stack Overflow

echo $var时,不会显示换行。需要使用双引号echo "$var"

条件判断

[]命令

[ EXPRESSION ] 等价于test EXPRESSION

  • STRING1 = STRING2: the strings are equal
  • STRING1 != STRING2: the strings are not equal
  • INTEGER1 -eq INTEGER2: INTEGER1 is equal to INTEGER2
  • INTEGER1 -ge INTEGER2: INTEGER1 is greater than or equal to INTEGER2
  • -n STRING: the length of STRING is nonzero
  • -z STRING: the length of STRING is zero
  • -d FILE: FILE exists and is a directory
  • -e FILE: FILE exists
  • -f FILE: FILE exists and is a regular file
  • arg1 OP arg2
    • OP is one of ‘-eq’, ‘-ne’, ‘-lt’, ‘-le’, ‘-gt’, or ‘-ge’. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers. When used with the [[ command, Arg1 and Arg2 are evaluated as arithmetic expressions (see Shell Arithmetic).

条件表达式 Bash Reference Manual (gnu.org)

[[ vs [ vs ( vs ((

shell - What is the difference between the Bash operators [[ vs [ vs ( vs ((? - Unix & Linux Stack Exchange

  • if [ condition ]

    [ is another name for the traditional test command. [ / test is a standard POSIX utility. All POSIX shells have it builtin (though that's not required by POSIX²). The test command sets an exit code and the if statement acts accordingly. Typical tests are whether a file exists or one number is equal to another.

  • if [[ condition ]]

    This is a new upgraded variation on test¹ from ksh that bash, zsh, yash, busybox sh also s matchesupport. This [[ ... ]] construct also sets an exit code and the if statement acts accordingly. Among its extended features, it can test whether a string a wildcard pattern (not in busybox sh).

  • if ((condition))

    Another ksh extension that bash and zsh also support. This performs arithmetic. As the result of the arithmetic, an exit code is set and the if statement acts accordingly. It returns an exit code of zero (true) if the result of the arithmetic calculation is nonzero. Like [[...]], this form is not POSIX and therefore not portable.

  • if (command)

    This runs command in a subshell. When command completes, it sets an exit code and the if statement acts accordingly.

    A typical reason for using a subshell like this is to limit side-effects of command if command required variable assignments or other changes to the shell's environment. Such changes do not remain after the subshell completes.

  • if command

    command is executed and the if statement acts according to its exit code.

正则判断

[[ expression ]]内 expression 可以使用正则判断 https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-_005b_005b

  • ==, !=
  • =~:using the POSIX regcomp and regexec interfaces usually described in regex(3)
  • 逻辑连接
    • ! expression
    • expression1 && expression2
    • expression1 || expression2
      • &&和||均有短路操作(不必判断全部表达式)

例子:

pattern='[[:space:]]*(a)?b'
[[ $line =~ $pattern ]]
if [[ $digit =~ [0-9] ]]; then
    echo "$digit is a digit"
else
    echo "oops"
fi

命令序列

命令连接符

Bash Reference Manual (gnu.org)- list of command

  • ;: 命令顺序执行
  • &&: 只有前一条成功运行才运行第二条
  • ||: 前面失败才运行后一条
  • &: 命令后台运行,也叫异步命令(asynchronous commands)The shell does not wait for the command to finish, and the return status is 0 (true)

其它

here-document(<<EOF)

用于给程序提供多行文本输入(text),EOF 表示分隔符,可以是其它字符串。

可用于避免交互输入,比如 passwd 时会交互式地输入密码,使用 here-document 将输入提前准备好即可。

$ wc << EOF
> one two three
> four five
> EOF
 2  5 24

here-string(<<<)

将一个提前准备好的字符串作为程序输入,同样用于避免交互。

bc <<< 5*4 #等价于echo '5*4' | bc

bash 中调用 python

set -x
var="/path/to/file.ext"
output=$(python <<EOF
var="$var"
var=var.split('/')[-1].split('.')[0]
print(var)
EOF
)

#output=$(python -c 'var="'$var'";var=var.split("/")[-1].split(".")[0];print(var)')
echo $output