Linux学习之bash学习之cookbook系列

马哥的淘宝店:https://shop592330910.taobao.com/bash cookbook 技巧来自http://www.catonmat.net/blogPart I: Working With Files 第一部分 文件处理1.清空文件内容 Empty a file (truncate to 0 size)$ > file这一行命令用到了...
摘要由CSDN通过智能技术生成

bash cookbook 技巧

来自http://www.catonmat.net/blog

Part I: Working With Files 第一部分 文件处理

1.清空文件内容 Empty a file (truncate to 0 size)

$ > file

这一行命令用到了输出重定向操作符>。输出重定向发生时,文件会被打开准备写入。如果此时文件不存在则先创建,存在则将其大小截取为0(truncate to 0)。这里我们并没有重定向写任何内容到文件中,所以文件依然保持为空。

如果你想替换文件的内容,或者创建一个包含指定内容的文件,可以运行下面的命令:

$ echo "some string" > file

如果你想往文件里面写入多行内容可以运行下面的命令:

cat << EOF > file
some string 1 line
stome string 
.....
EOF

2.追加内容到文件

$ echo "foo bar baz" >> file     

这个命令用到了另外一个输出重定向操作符>>,该操作符将内容追加到文件。同样地,如果文件不存在则先创建它。追加的内容之后,紧跟着换行符。如果你不想要追加换行符,在执行echo命令时可以指定-n选项:

$ echo -n "foo bar baz" >> file

在使用输出重定向的时候,bash可以设置个 set -C 来禁止覆盖已经存在的文件

$ set -C
$ echo "foo bar baz" > file 
bash: file: cannot overwrite existing file     


此时如果确实想覆盖此文件可以使用>| 符号。

3.读取文件的首行并赋值给变量

$ read -r line < file

这一行命令用到了 Bash 的内置命令read,和输入重定向操作符<。read命令从标准输入中读取一行,并将内容保存到变量line中。在这里,-r选项保证读入的内容是原始的内容(raw),意味着反斜杠转义的行为不会发生。输入重定向操作符< file打开并读取文件file,然后将它作为read命令的标准输入。

记住,read命令会删除包含在IFS变量中出现的所有字符,IFS 的全称是 Internal Field Separator(内部字段分隔符),Bash 根据 IFS 中定义的字符来分隔单词。在这里,read命令读入的行被分隔成多个单词。默认情况下,IFS包含空格,制表符和回车,这意味着开头和结尾的空格和制表符都会被删除。如果你想保留这些符号,可以通过设置IFS为空来完成:

$ IFS= read -r line < file       

IFS 的变化仅会影响当前的命令,这行命令可以保证读入原始的首行内容到变量line中,同时行首与行尾的空白字符被保留。

另外一种读取文件首行内容,并赋值给变量的方法是:

$ line=$(head -1 file)

这里用到了命令替换操作符$(...),它运行括号里的命令并且将输出返回。 这个例子中,命令是head -1 file,输出的内容是文件的首行。输出然后通过等号赋值给变量line$(...)的等价写法是...,所以也可以换成下面这样:

$ line=`head -1 file`

不过,在 Bash 中$(...)用法更加推荐,因为它看起来更加整洁,并且容易嵌套使用。

4.依次读入文件每一行

$ while read -r line; do
    # do something with $line 

done < file

这是一种正确的读取文件内容的做法,read命令放在while循环中。当read命令遇到文件结尾时(EOF),它会返回一个正值,导致循环判断失败终止。

记住,read命令会删除首尾多余的空白字符,所以如果你想保留,请设置 IFS 为空值:

$ while IFS= read -r line; do
    # do something with $line  

done < file

如果你不想将< file放在最后,可以通过管道将文件的内容输入到 while 循环中:

$ cat file | while IFS= read -r line; do
    # do something with $line    

done

对这里有个说明:对于循环读取标准输入的操作,很多程序内置有自己的标准输入链接到相同的输入源上面,和read命令一样。它偶尔会产生扭曲的结果。
另一种方法是从不同的文件描述符读取数据。

exec 3< input_file.txt                # open input_file.txt on fd 3

while read -u 3 -r line ; do
    # do stuff here     

done

exec 3<&-                             # close fd 3

对于这个通过管道传给while循环的这个例子需要特别注意一点,这个while循环将会创建一个subshell子shell,之前的一些变量在这个while中是不存在的。

i=0
cat foo.txt | while read line; do ((i++)); done
echo "$i"

#will print 0. 
 i=0;cat foo.txt | (while read line; do ((i++)); done; echo "$i")

对于bash4.X可以使用mapfile内置命令来读取文件的一行

mapfile ARRAY < file

这个命令也有一些选项
-s count - skip the first count lines
-n count - read in at most count lines
-c quanta - set a quanta for the -C option
-C command - run command every quanta lines passing the index of the array about to be assigned
-0 index - start assigning at array[index] instead of 0
-t - strip trailing newline
-u fd - read from file descriptor fd instead of stdin

5.随机读取一行并赋值给变量

$ read -r random_line < <(shuf file)      

Bash 中并没有提供一种直接的方法来随机读取文件的某一行内容,所以这里需要利用外部程序。在最新的一些 Linux 系统上,GNU Coreutils 包中提供的shuf命令可以满足我们的需求。

这一行命令中用到了进程替换(process substitution)操作符<(...)。进程替换操作会创建一个匿名的管道文件,并将进程命令的标准输出连接到管道的写一端。然后 Bash 开始执行进程替换中的命令,然后将整个进程替换的表达式替换成匿名管道的文件名。

当 Bash 看到<(shuf file)时,它首先打开一个特殊的文件/dev/fd/n,这里的n是一个空闲的文件描述符,然后执行shuf file命令,将标准输出连接到/dev/fd/n,并且替换<(shuf file)/dev/fd/n,因此实际的命令会变成:

$ read -r random_line < /dev/fd/n               

结果会读取洗牌后的文件的第一行内容。

另外一种做法是,使用 GNU sort 命令,它提供的-R选项可以随机排序文件:

$ read -r random_line < <(sort -R file)            

或者,同前面一样,将结果赋值给变量:

$ random_line=$(sort -R file | head -1)         

这里,我们首先通过sort -R随机排序文件,然后通过head -1 读取文件的第一行。

6.读取文件首行前三个字段并赋值给变量

$ while read -r field1 field2 field3 throwaway; do
    # do something with $field1, $field2, and $field3
done < file

如果在read命令中指定多个变量名,它会将读入的内容分隔成多个字段,然后依次赋值给对应的变量,第一个字段赋值给第一个变量,第二个字段赋值给第二个变量,等等,最后将剩余的所有字段赋值给最后一个变量。这也是为什么在上面的例子中,我们加了一个throwaway变量,否则的话,当文件的一行大于三个字段时,第三个变量的内容会包含所有剩余的字段。

有时候,为了书写方便,可以简单地用_来替换throwaway变量:

$ while read -r field1 field2 field3 _; do
    # do something with $field1, $field2, and $field3       
done < file

又或者,如果你的文件确实只有三个字段,那可以忽略它:

$ while read -r field1 field2 field3; do
    # do something with $field1, $field2, and $field3           
done < file

下面是一个例子,假如你想知道一个文件到底包含多少行,多少个单词以及多少个字节。当你执行wc命令时,你会得到3个数字加上文件名,文件名在最后:

$ cat file-with-5-lines
x 1
x 2
x 3
x 4
x 5
$ wc file-with-5-lines
 5 10 20 file-with-5-lines

所以,这个文件包含5行,10个单词,以及20个字符。我们接下来,可以通过read命令将这些信息保存到变量中:

$ read lines words chars _ < <(wc file-with-5-lines)

$ echo $lines
5
$ echo $words
10
$ echo $chars
20

类似地,你也可以使用 here-strings 将字符串分隔并保存到变量中。假设你有一个字符串变量$info,内容为"20 packets in 10 seconds",然后你想要将从中获取20和10。在不久之前,我是这样来完成的:

$ packets=$(echo $info | awk '{ print $1 }')
$ time=$(echo $info | awk '{ print $4 }')

然而,得益于read命令的强大和对 Bash 的了解,我们可以这样做:

$ read packets _ _ time _ <<< "$info"

这里,<<< 就是 here-string 的语法,它允许你直接传递字符串给标准输入。

7.保存文件的大小到变量

$ size=$(wc -c < file)

这一行命令中用到了第3点中介绍的命令替换操作$(…),它运行里面的命令并将结果获取回来。在这个例子中,命令是wc -c < file,它输出文件的字节数。这个结果最终会赋值给变量size。
这里如果直接执行wc -c file 的话结果会带个文件名称的,这里使用输入重定向就不会带文件名称了。

8.从文件路径中获取文件名

假设,你有一个文件,它的路径为/path/to/file.ext,然后你要从中获取文件名,在这里是file.ext。你要怎么做? 一个好的方法是通过参数展开(parameter expansion)功能:

$ filename=${path##*/}

这一行命令使用了参数展开的语法:${var##pattern},它从$var字符串开始处开始匹配pattern。如果能够匹配成功,将最长匹配的内容删除后再返回。

在这个例子中,匹配的模式是*/,它尝试匹配/path/to/file.ext的开始部分,正如前面所说,这里是贪婪匹配,所以它能够匹配到最后一个斜杠为止,即匹配的内容是/path/to/。所以当把匹配的内容删除后,返回的内容就是文件名file.ext。
这里的井在键盘的左边,表示从左边开始匹配,2个井号表示尽可能多的匹配。

对此也可以使用basename命令

filename=$(basename $path)

9.从文件路径中获取目录名

和上面一样类似,这次你要从路径/path/to/file.txt中获取目录名/path/to。你可以继续通过参数展开功能来完成这个任务:

$ dirname=${path%/*}

这次的用法是${var%pattern},它从$var的结尾处匹配/*。如果能够成功匹配,将最短匹配的内容删除再返回。

在这个例子中,匹配的模式是/*,它能够匹配/file.ext部分,删除这部分内容后返回的就是目录名称。
通用的百分号在键盘的右边,表示从右边开始匹配,一个百分号表示尽可能少的匹配的。

对此也可以使用dirname命令

dirname=$(dirname $path)

注意:basename 和 dirname不是bash的内置命令,这个2个是个外部命令。

10.快速拷贝文件

假设你要将文件 /path/to/file 拷贝到/path/to/file_copy,一般情况下会这么来写:

$ cp /path/to/file /path/to/file_copy

不过,你可以利用花括号展开(brace expansion){...}功能:

$ cp /path/to/file{,_copy}

花括号展开可以生成任意字符串的组合,在这个例子中,/path/to/file{,_copy}
终生成/path/to/file /path/to/file_copy。所以上面这行命令最终发型成:

$ cp /path/to/file /path/to/file_copy

或者是文件带扩展名的

cp /long/path/to/file{,_bk}.ext

类似地,你可以执行下面的命令快速的移动文件:

$ mv /path/to/file{,_old}

这行命令展开后就变成了:

$ mv /path/to/file /path/to/file_old
function bk {
 if [[ -z $1 ]]; then
    echo "Usage: bk <file>"
    return
 fi

 file=$(basename $1)
 bk=_bk

 while :; do
  case $file in
   *.*)
    newfile=$(echo $file | sed 's/\(.*\)\.\(.*\)/\1'$bk'.\2/')
    ;;
   *)
    newfile=${file}$bk
    ;;
  esac
  if [[ ! -e $newfile ]]; then
   break
  fi
  bk=${bk}_bk
 done

 cp "$1" "$(dirname $1)/$newfile"
 if [[ $? -eq 0 ]]; then
    vim "$1"
 fi
}

Part II: Working With Strings 第二部分 字符串处理

1.生成alphabet字母表

$ echo {a..z}  

这个技巧中又用到了花括号展开。利用它我们可以生成任意的字符串,例如{x…y},其中 x 和 y 都是单个字符,这个表达式展开后包含 x 与 y 之间的所有字符。注意里面是2个点号。

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z

$ echo {x..y}
x y

$ echo {x..z}
x y z

2.生成不包含空格的字母表字符串

$ printf "%c" {a..z}
abcdefghijklmnopqrstuvwxyz$ 


这个技巧非常棒。如果你在printf命令之后指定一个列表,最终它会循环依次打印每个元素,直到完成为止。printf就像一个循环。
这个技巧中p

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shell scripting is a way to harness and customize the power of any Unix system, and an essential skill for Unix users, system administrators, and even professional Mac OS X developers. But beneath this simple promise lies a treacherous ocean of variations in Unix commands and standards. This thoroughly revised edition of bash Cookbook teaches shell scripting the way Unix masters practice the craft. Three Unix veterans present a variety of recipes and tricks for all levels of shell programmers so that anyone can become a proficient user of the most common Unix shell—the bash shell—and cygwin or other popular Unix emulation packages. This cookbook is full of useful scripts that readers can use right away, along with examples that explain how to create better scripts. Table of Contents Chapter 1. Beginning Bash Chapter 2. Standard Output Chapter 3. Standard Input Chapter 4. Executing Commands Chapter 5. Basic Scripting: Shell Variables Chapter 6. Shell Logic And Arithmetic Chapter 7. Intermediate Shell Tools I Chapter 8. Intermediate Shell Tools Ii Chapter 9. Finding Files: Find, Locate, Slocate Chapter 10. Additional Features For Scripting Chapter 11. Working With Dates And Times Chapter 12. End-User Tasks As Shell Scripts Chapter 13. Parsing And Similar Tasks Chapter 14. Writing Secure Shell Scripts Chapter 15. Advanced Scripting Chapter 16. Configuring And Customizing Bash Chapter 17. Housekeeping And Administrative Tasks Chapter 18. Working Faster By Typing Less Chapter 19. Tips And Traps: Common Goofs For Novices Appendix A Reference Lists Appendix B Examples Included With Bash Appendix C Command-Line Processing Appendix D Revision Control
Shell scripting is a way to harness and customize the power of any Unix system, and an essential skill for Unix users, system administrators, and even professional Mac OS X developers. But beneath this simple promise lies a treacherous ocean of variations in Unix commands and standards. This thoroughly revised edition of bash Cookbook teaches shell scripting the way Unix masters practice the craft. Three Unix veterans present a variety of recipes and tricks for all levels of shell programmers so that anyone can become a proficient user of the most common Unix shell—the bash shell—and cygwin or other popular Unix emulation packages. This cookbook is full of useful scripts that readers can use right away, along with examples that explain how to create better scripts. Table of Contents Chapter 1. Beginning Bash Chapter 2. Standard Output Chapter 3. Standard Input Chapter 4. Executing Commands Chapter 5. Basic Scripting: Shell Variables Chapter 6. Shell Logic And Arithmetic Chapter 7. Intermediate Shell Tools I Chapter 8. Intermediate Shell Tools Ii Chapter 9. Finding Files: Find, Locate, Slocate Chapter 10. Additional Features For Scripting Chapter 11. Working With Dates And Times Chapter 12. End-User Tasks As Shell Scripts Chapter 13. Parsing And Similar Tasks Chapter 14. Writing Secure Shell Scripts Chapter 15. Advanced Scripting Chapter 16. Configuring And Customizing Bash Chapter 17. Housekeeping And Administrative Tasks Chapter 18. Working Faster By Typing Less Chapter 19. Tips And Traps: Common Goofs For Novices Appendix A Reference Lists Appendix B Examples Included With Bash Appendix C Command-Line Processing Appendix D Revision Control

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值