在Bash中使用别名、脚本和新函数
1. 概述
在本教程中,我们将讨论定义别名、使用 Bash函数 和创建新的shell 脚本 的用例。首先,我们将回顾这三个 Bash 工具的显着特点。然后,我们将深入讨论基于其独特功能的用例。
2. 背景
让我们仔细看看 Bash 别名、函数和脚本为我们提供的特性。
2.1. Bash 别名的显着特征
Bash 别名是一种为长命令或命令序列创建简写的方法。我们可以使用alias命令在 Bash 中创建别名:
$ alias rm='rm -i'
这将确保每当我们在终端上键入rm 命令时,Bash 都会将其替换为rm -i。因此,我们将为每个删除操作使用交互模式:
$ touch testfile && rm testfile
rm: remove regular empty file 'testfile'? n
$
我们可以通过将它放在*~/.bashrc * 文件中来使这个别名永久化,并且它将可用于交互式子shell。我们可以使用p选项打印所有可用的别名:
$ alias -p
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
默认情况下,别名在 shell 脚本中不可用——例如,在非交互式 shell中。但是,我们可以使用 shell 选项启用它们:
shopt -s expand_aliases
此外,~/.bashrc不会被 shell 脚本读取,因此,如果~/.bashrc*文件包含我们想要使用的别名,我们必须显式获取它:*
#!/bin/bash
shopt -s expand_aliases
source $HOME/.bashrc
alias welcome='echo "Welcome to the tutorial!"'
welcome
让我们也执行脚本来验证输出:
$ ./test_alias.sh
Welcome to the tutorial!
我们应该尝试限制在 shell 脚本中使用别名。如果别名被删除或在不同的环境中执行,脚本可能会中断。
2.2. Bash 函数的显着特点
与别名类似,我们也可以在 Bash 启动文件中添加函数。我们可以使用typeset命令检查 shell 中所有可用函数的列表:
$ typeset -F | tail -10
declare -f _usergroup
declare -f _userland
declare -f _variables
declare -f _xfunc
declare -f _xinetd_services
declare -f command_not_found_handle
declare -f dequote
declare -f quote
declare -f quote_readline
declare -f welcome
在这里,我们添加了tail命令以仅打印终端上的最后 10 行。此外,我们可以阅读 Bash 函数的源代码:
$ declare -f welcome
welcome ()
{
echo "Welcome to the tutorial, $1."
}
让我们测试一下我们welcome的Bash 函数:
$ welcome Ann
Welcome to the tutorial, Ann.
正如我们所看到的,这些函数比别名功能丰富得多。函数更具程序性,我们可以在其中使用循环和条件。最重要的是,我们可以将参数传递给函数。
函数的另一个重要方面是我们可以export 它们。这使得它们可用于从定义它们的环境中执行的 shell 脚本。让我们导出我们的函数:
$ export -f welcome
我们可以将此语句添加到*~/.bashrc*启动文件中。
现在,添加 Bash 函数并将它们导出到*~/.bashrc文件中是合法的。但是,*如果我们有大量函数,将它们保存在单独的隐藏文件~/.bash_functions中**并在*~/.bashrc文件中获取它可能更实用。这具有保持我们的~/.bashrc*文件相对干净的额外优势。
别名和 Bash 函数的内容保存在 shell 的内存中。因此,不会创建新的子 shell 来执行它们。
2.3. Bash 脚本的显着特点
Bash 脚本不保存在 shell 的内存中。**每当执行脚本时,都会派生一个新的子 shell(非交互式 shell)来执行脚本。**在子shell 中,脚本由/shebang 行中指定的解释器执行(例如,#!/bin/bash)。但是,如果需要,我们也可以使用source命令在当前 shell 中执行脚本。
让我们创建一个简单的脚本来解析 CSV 文件:
#! /bin/bash
while IFS="," read -r rec_column1 rec_column2 rec_column3 rec_column4
do
echo "Displaying Record-$rec_column1"
echo "Record2: $rec_column2"
echo "Record3: $rec_column3"
echo "Record4: $rec_column4"
echo ""
done < <(tail -n +2 input.csv)
此脚本读取具有4列的 CSV 文件并在终端上打印值。
3. 理解用例
现在让我们深入讨论 Bash 别名、脚本和函数的用例。
3.1.何时创建 Bash 别名
别名的用例非常简单。如果我们过于频繁地使用一个命令或短序列的命令,我们可能应该尝试为它创建一个别名。一个例子是创建一个别名来以漂亮的打印和图形格式显示 git 日志:
$ alias glog='git log --graph --abbrev-commit --decorate --date=relative --all'
此后,我们可以在终端上简单地键入glog作为上述命令的简写。
3.2. 何时编写 Bash 函数
正如我们在前几节中看到的,别名有一定的限制。如果我们重复做的事情太复杂而不能成为别名,我们应该创建一个 Bash 函数。例如,我们可能想要创建一个函数来执行一系列git命令:
function gcommit()
{
git status
git add -A
git commit -m "$1"
}
export -f gcommit
函数就像内存中的 shell 脚本。因此,**如果我们想修改当前 shell 的环境,**比如更改工作目录 或设置环境变量 ,我们应该更喜欢函数而不是 shell 脚本。 让我们创建一个函数来遍历目录结构:
function traverse_up()
{
new_dir=""
up_dir="$1"
for i in `seq 1 $up_dir`;
do
new_dir="$new_dir"'../'
done
cd $new_dir
echo $PWD
}
export -f traverse_up
一旦我们在当前环境中设置了这个函数,我们就可以对其进行测试:
$ echo $PWD && traverse_up 3
/home/shubh/bael/tutorials/linux-bash/functions
/home/shubh/bael
在这里,使用traverse_up 3与键入*cd ../../..*命令一样好。
3.3. 何时编写 Bash 脚本
最后,脚本是理想情况下应该独立于环境并且应该独立存在的东西。如果某些东西是我们很少使用的非重复性任务或实用程序,我们应该为它创建一个脚本而不是别名或函数。
每当我们想将功能扩展到当前 shell 之外,或者如果我们需要 shell 之外的程序来利用这些功能,我们应该为它创建一个脚本。