有关bash,我希望我能知晓的十件事(代码片段)

woshijiuke woshijiuke     2022-11-18     151

关键词:

简介

我之前的一篇文章比我预想的更受欢迎,因此我想再写一篇文章来介绍一些不太知名的bash功能

正如之前所言,由于我觉得bash是一种要经常使用(且需理解)的技术,所以我在研究bash时写了一本书。虽然许多人并不熟悉bash,但我觉得他们也认为非常重要便足够令人欣喜。

1)^x^y^

我总在使用的一个小技巧。

从来没有输入过类似的命令?

$ grp somestring somefile
-bash: grp: command not found

哎,这个命令敲错了,所以你要敲“↑”,然后敲”←“直到”p“,然后输入”e"再执行。

或者这样输入:

$ ^rp^rep^
grep ‘somestring‘ somefile
$

你可能需要注意的一个细节是:

$ grp rp somefile
$ ^rp^rep^
$ grep rp somefile

如果你想搜索“rep”,那你就要深入研究man page,学会使用这个更强大的命令:

$ grp rp somefile
$ !!:gs/rp/rep
grep rep somefile
$

我不会在这里解释这个用法。。。

2)pushd/popd

这个在脚本中非常好用,特别是在循环中

如下所示,假设你正在写一个进入退出文件夹的for循环:

for d1 in $(ls -d */)
do
 # Store original working directory.
 original_wd="$(pwd)"
 cd "$d1"
 for d2 in $(ls -d */)
 do
   pushd "$d2"
   # Do something
   popd
 done
 # Return to original working directory
 cd "$original_wd"
done

你可以像这样使用pushd栈来重写上方代码:

for d1 in $(ls -d *)
do
 pushd "$d1"
 for d2 in $(ls  -d */)
 do
   pushd "$d2"
   # Do something
   popd
 done
 popd
done

它可以追踪记录你切换的目录并进行入栈或出栈

注意,当使用pushd出现错误时,可能会丢失栈的记录并且popd多次。因此你可能会想要在脚本中使用set -e(见上一篇文章)

当然也可以用cd -,但是它不会使用栈——仅仅返回前一个目录

cd ~
cd /tmp
cd blah
cd - # Back to /tmp
cd - # Back to ‘blah‘
cd - # Back to /tmp
cd - # Back to ‘blah‘ ...

3) shopt vs set

这两个命令困扰了我一阵子。

两者之间有什么不同呢?

set在之前的文章已经介绍过了,而shopt看起来与之相似。只输入shopt会显示一系列选项:

$ shopt
cdable_vars    off
cdspell        on
checkhash      off
checkwinsize   on
cmdhist        on
compat31       off
dotglob        off

我在这里( here)找到了一些答案。

从根本上说,似乎有一系列的bash(和其他shells)建立在sh之上,而添加shopt命令则为设置额外的shell选项提供了一种方式

但是我也不确定……如果你知道为什么,请告诉我。

4)Here Docs 与 Here Strings

“Here Docs”是在shell中用一些语句创建的文件。

“诀窍”很简单。定义一个用于结束的单词,则在这个单词单独出现在一行之前的所有输入行将构成文件。

像这样:

$ cat > afile << SOMEENDSTRING
> here is a doc
> it has three lines
> SOMEENDSTRING alone on a line will save the doc
> SOMEENDSTRING
$ cat afile
here is a doc
it has three lines
SOMEENDSTRING alone on a line will save the doc
$

注意:

· 如果结束单词不是“单独”出现在一行中,那它可以构成文件

· SOMEENDSTRING通常是END,但这仅仅只是习惯

更鲜为人知的是“here string”:

$ cat > asd <<< ‘This file has one line‘

5)字符串变量的操作

以前你可能是像下面展示的那样写代码,用sed一类的工具来操作字符串:

$ VAR=‘HEADERMy voice is my passwordFOOTER‘
$ PASS="$(echo $VAR | sed ‘s/^HEADER(.*)FOOTER/1/‘)"
$ echo $PASS

但是你可能不知道bash本身也是可以的。

这意味着你可以省去大量的sed和awk。

一种重写上述代码的方式如下所示:

$ VAR=‘HEADERMy voice is my passwordFOOTER‘
$ PASS="$VAR#HEADER"
$ PASS="$PASS%FOOTER"
$ echo $PASS

·#表示“从字符串开头开始匹配并删除所给的模式串”

·%表示“从字符串结尾开始匹配并删除所给的模式串”

在我的电脑上,后一种方法比前一种快两倍。并且(令我吃惊的是),他的速度跟类似功能的python脚本速度大致相当

如果你想使用通配符(见前文)模式串并采用贪婪模式,你需要双写:

$ VAR=‘HEADERMy voice is my passwordFOOTER‘
$ echo $VAR##HEADER*

$ echo $VAR%%*FOOTER

6)变量的默认值

这些对写脚本来说非常好用。

如果你有一个没有赋值的变量,你可以像这样给它“赋默认值”

创建一个default.sh文件,写入如下内容:

#!/bin/bash
FIRST_ARG="$1:-no_first_arg"
SECOND_ARG="$2:-no_second_arg"
THIRD_ARG="$3:-no_third_arg"
echo $FIRST_ARG
echo $SECOND_ARG
echo $THIRD_ARG

现在执行chmod +x default.sh并用./default.sh first second来运行脚本:

观察第三个参数的默认值是如何被分配的,而不是前两个。

你也可以直接用$VAR:=defaultval(等号,不是破折号),但是注意这不适用于脚本或函数中的位置变量。尝试修改上面的脚本来看它是如何失败的。

7)Traps

当一个信号被送到脚本时,内建的trap可以用于“捕获”

下面是我用在自己的chepci脚本中的一个例子:

function cleanup() 
   rm -rf "$BUILD_DIR"
   rm -f "$LOCK_FILE"
   # get rid of /tmp detritus, leaving anything accessed 2 days ago+
   find "$BUILD_DIR_BASE"/* -type d -atime +1 | rm -rf
   echo "cleanup done"                                                                                                                          
 
trap cleanup TERM INT QUIT

任何使用TERM信号的CTRL-C,CTRL-或终止程序的操作将会首先调用cleanup

注意:

·trap的逻辑可能非常棘手(例如处理信号竞争条件)

·KILL信号不能以这种方式捕获

但是大多数情况下,我会把它用于类似上述的‘cleanup’中,来达成函数的目的。

8)Shell变量

了解可用的标准shell变量是非常值得的。这些是我最喜欢的。

RANDOM

不要依赖这个来加密堆栈,但你可以生成随机数字,例如在脚本中创建临时文件时:

$ echo $RANDOM
16313
$ # Not enough digits?
$ echo $RANDOM$RANDOM
113610703
$ NEWFILE=/tmp/newfile_$RANDOM
$ touch $NEWFILE

REPLY

不在需要给read一个变量名称

$ read
my input
$ echo $REPLY

LINENO 与 SECONDS

方便调试

$ echo $LINENO
115
$ echo $SECONDS; sleep 1; echo $SECONDS; echo $LINENO
174380
174381
116

注意,即便使用;来隔开命令,上面的代码也要分两行

TMOUT

可以用来超时读取,在一些脚本中真的很好用

#!/bin/bash
TMOUT=5
echo You have 5 seconds to respond...
read
echo $REPLY:-noreply

9) Extglobs

如果你真的沉迷bash不能自拔,那么你可能想要增强你的通配功能。你可以通过设置shell中的extglob选项。这是设置方法:

shopt -s extglob
A="12345678901234567890"
B="  $A  "

现在来看看你是否能指出以下这些语句各自的功能:

echo "B      |$B|"
echo "B#+( ) |$B#+( )|"
echo "B#?( ) |$B#?( )|"
echo "B#*( ) |$B#*( )|"
echo "B##+( )|$B##+( )|"
echo "B##*( )|$B##*( )|"
echo "B##?( )|$B##?( )|"

虽然它可能很有用,但是很难想象出一种你必须要用这种方式的情况。通常你会使用一些更适合相应任务的工具(像sed)或者直接放弃bash去使用一些像python那样的“合适的”编程语言。

10)关联数组

谈到移植到其他语言,一条重要的规则是,如果我需要用到数组,那么我会放弃bash,使用python(为此我甚至创建了一个Docker Container来运行一个专门的工具)

知道读到它我才知道,在bash中有关联数组

以下是演示:

$ declare -A MYAA=([one]=1 [two]=2 [three]=3)
$ MYAA[one]="1"
$ MYAA[two]="2"
$ echo $MYAA
$ echo $MYAA[one]
$ MYAA[one]="1"
$ WANT=two
$ echo $MYAA[$WANT]

注意仅适用于bash4.x+版本

看完以上的内容,相信你对于Linux运维的了解又加深了一层。作为一名Linux爱好者,如果你在学习中遇到了困惑需要交流,可以来我们的网站(http://www.magedu.com/)获取帮助,了解行业评价最高的Linux课程可以拨打电话:18519746220。

关于token,你应该知道的十件事

转自:http://ju.outofmemory.cn/entry/134189原文是一篇很好的讲述Token在Web应用中使用的文章,而这是我和 Special 合作翻译的译文。1.Token应该被保存起来(放到local/sessionstograge或者cookies)在单页应用程序中,有些用户刷新浏览器... 查看详情

大学里的十件事十本书十部电影

:【大学里的十件事、十本书、十部电影!(精华版)】1、大学里要做的10件事1.学习计算机,通过二级考试,并学习其它电脑知识。不是为了拿到证书而炫耀,而是为了以后学习其它电脑知识的便利2.认真学习英语,顺利通过... 查看详情

solaris:你好奇的十件事

想想你周围的人,看看他们正在使用的操作系统。绝大部分人的电脑都在用主流操作系统:Windows,MacOS,甚至是Ubuntu。当说到Solaris,Unix和BSD的时候,其他人还以为你说鸟语呢。除了IT狂人和在工作、学术环境中使用它的人,他... 查看详情

惹毛程序员的十件事!需求变更居然不是排第一

本文转载自程序员编程社区如何惹毛一名开发者?再好脾气的程序员,总能被下面一条逼疯,你中了几条呢?第十位程序注释程序注释本来是一些比较好的习惯,当程序员老手带新手的时候,总是会告诉新... 查看详情

《百万it毕业生的心声:it专业大学生毕业前必做的十件事》

0001、搞定linux操作系统Linux是一个开源的操作系统,但总是拿开源说事的话,对于没有深入了解的同学来说可能不是能很清楚的认识这个概念。这里我换个角度用大白话聊一聊linux,linux其实是属于喜欢“折腾”的人的... 查看详情

springcloudeureka总结(代码片段)

...事,没有真正悟到它的原理,认清它的本质。2019年,我希望我能戒掉周末还有时间打游戏的生活状态,能充实自己,克服焦虑;2019年,我希望我能坚持,能勤奋;2019年,我希望我能多读书,能成长;2019年,我希望我能坦然面... 查看详情

拿到offer过后--大学最后时光最想做的那十件事

     昨天——2014.10.26,历史性的一刻,激动的签了欢聚时代(YY)的前端开发offer,工作地点是我喜欢的珠海(仅仅由于那边有我所向往的海还有自行车队,如今想想都乐开怀了,绕着海边骑单车的感觉真妙)... 查看详情

35岁前十件事该做好

第一,学会本行业所需要的一切知识并有所发展。 每个人在年轻时都可能有过彻夜不眠、刻苦攻读,这在20岁甚或25岁都没有问题,但到了35岁,就不应该再为学习基本技能而大伤脑筋了。35岁之前是一个人从事原始积累的阶... 查看详情

网站优化——建站前期请不要干这十件事

网站优化,成功让搜索引擎收录并且获得好的排名是最终我们优化的最终目的。但是在建站初期我们还是要注意一些不利于优化的错误要去避免:   1:首页的做法   首页最忌讳的做法是整体页面都做成一... 查看详情

java异常处理的十个建议(代码片段)

前言Java异常处理的十个建议,希望对大家有帮助~本文已上传github:https://github.com/whx123/JavaHome公众号:捡田螺的小男孩一、尽量不要使用e.printStackTrace(),而是使用log打印。反例:try//dowhatyouwantcatch(Exceptione)e.printStackTrace();正例:try//do... 查看详情

flutter-ui-基础控件(代码片段)

...走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。小知识1.int_currentInd... 查看详情

覆盖每个命令的bash完成(代码片段)

...有未设置特定完成的命令定义“默认”完成过程。如果您希望默认值应用于所有命令,则不要设置任何特定的完成。如果要 查看详情

在 bash 循环中访问文件特征/属性

...【发布时间】:2018-12-2920:13:53【问题描述】:我正在学习有关bash脚本的更多信息。循环浏览目录中的文件时,我希望能够回显的不仅仅是文件名。如何访问关联的文件数据?这个示例代码我用来列出文件夹中的所有文件。forfilei... 查看详情

我希望我能记得

https://www.chrisjmendez.com/2008/03/23/mysql-commands-i-wish-i-could-remember/https://www.chrisjmendez.com/2008/03/23/mysql-commands-i-wish-i-could-remember/ 查看详情

使用swift在nstextfield中垂直对齐文本(代码片段)

我一直在阅读有关如何在NSTextField上设置垂直对齐的各种选项。我希望文本显示在中心,并在Swift中以编程方式进行。以下是我目前看到的事情:http://www.cocoabuilder.com/archive/cocoa/174994-repositioning-an-nstextfieldcell.htmlhttps://red-sweater.com/... 查看详情

使用自制软件安装r后的终端(代码片段)

...么能解决/摆脱这些出现在终端上。我认为这与以下内容有关:$echo"exportLC_ALL=en_US.UTF-8">>~/.bash_profile$echo"exportLANG=en_US.UTF-8">>~/.bash_profile$echo"exportPATH=/usr/local/bin:$PATH">>~/.bash_profile&&source~/.bash_profile答案instructionsth... 查看详情

如何使用 Bash 读取超时?

...用sleep让他等待。但我想不出同时做这两件事的方法。我希望用户可以选择:按Ctrl+C取消,Enter继续或等待10秒我该怎么做?【问题讨论】:【参考方案1】:在bash中,read有一个-t选项,您可以在其中指定超时。从手册 查看详情

如何使用 Bash 读取超时?

...用sleep让他等待。但我想不出同时做这两件事的方法。我希望用户可以选择:按Ctrl+C取消,Enter继续或等待10秒我该怎么做?【问题讨论】:【参考方案1】:在bash中,read有一个-t选项,您可以在其中指定超时。从手册 查看详情