Bash Shell

redirect

> 写入文件时覆盖原文件
>> 从文件后面累加
2> 2>> 输出错误信息
$ find /home -name hh > a 2> b 将正确数据输出到a,错误数据输出到b
$ find /home -name hh > a 2>&1 将数据都输出到a
如果想要抛弃错误信息 $ find /home -name hh > a 2> /dev/null /dev/null不会接收任何输入

双重redirect

$ tee filename #将数据存入file后再传给下一个命令

通配符、组合按键和特殊符号

符号含义
*匹配0或多个
?匹配一个
&将命令在后台运行
>替换
>>累加
[]中间是字符的组合
()中间是一个子shell
``中间是先执行的命令
组合按键含义
^DEOF
^MEnter键
^S暂停屏幕输出
^Q恢复屏幕输出
^U在提示符在,删除整行命令
^Z暂停当前命令

单引号和双引号区别

单引号不会转义

$ name=33
$ echo "$name"
33
$ echo '$name'
$name

变量操作

基本操作

$ name="3 3"
$ name=${name}hh
$ echo $name
3 3hh

$ env #显示用户的环境变量
$ set #显示用户的局部变量和用户环境变量
export #显示用户由局部变量导出成环境变量 的变量
export name #将自定义变量导入环境变量

反单引号``
``之内的命令将先执行,其结果作为外部输入信息

$ ls -l `locate crontab`
#先用locate将所有文件名数据列出,再ls列出详细内容

read 读输入

$ read b
34
$ echo $b
34

$ read -p "in: " a
in: 33
$ echo $a
33

$ read -t 3 #等待用户输入三秒,没有则结束

declare 声明变量属性

$ declare -a sum=(1 3 56)
$ echo ${sum[1]} #将sum定义为叔祖

$ sum=100+123
$ echo $sum
100+123
$ declare -i sum=100+123 #将sum定义为interger
$ echo $sum
223

$ declare -x sum # 将sum变成环境变量

$ declare -r sum #将sum变成read only
$ sum=222 #error

ulimit 设置文件系统与程序的限制关系

字符标志作用#*%
# 是 去掉左边(键盘上#在 $ 的左边)
%是去掉右边(键盘上% 在$ 的右边)
单一符号% #是最小匹配;两个符号## %%是最大匹配
* 表示零个或多个任意字符
? 表示零个或一个任意字符
[…] 表示匹配中括号里面的字符
[!..] 表示不匹配中括号里面的字符

$ v="00/111/222/333/444.55"
$ echo ${v#*/} #  删掉第一个 / 及其左边的字符串
111/222/333/444.55
$ echo ${v##*/} #  删掉最后一个 / 及其左边的字符串
444.55

$ echo ${v%/*} #  删掉最后一个  /  及其右边的字符串
00/111/222/333
$ echo ${v%%/*} #  删掉第一个  /  及其右边的字符串
00

$ echo ${v:5:5}
1/222
$ echo ${v::3}
00/
$ echo ${v:4:-2}
11/222/333/444.

$ v=22.3322.44.5
$ echo ${v/22/_} #替换
_.3322.44.5
$ echo ${v//22/_}
_.33_.44.5

利用 ${ } 还可针对不同的变数状态赋值(沒设定、空值、非空值):
一般: “str:“代表"str"没设置或者为空, "str“代表没设置

$ file=/dir1/dir2/dir3/my.file.txt
$ ${file-my.file.txt} #假如 $file 没有设定,則使用 my.file.txt 作传回值。(空值及非空值時不作处理) 
$ ${file:-my.file.txt} #假如 $file 沒有設定或為空值,則使用 my.file.txt 作傳回值。 (非空值時不作处理)
$ ${file+my.file.txt} #假如 $file 設為空值或非空值,均使用 my.file.txt 作傳回值。(沒設定時不作处理)
$ ${file:+my.file.txt} #若 $file 為非空值,則使用 my.file.txt 作傳回值。 (沒設定及空值時不作处理)
$ ${file=my.file.txt} #若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt 。 (空值及非空值時不作处理)
$ ${file:=my.file.txt} #若 $file 沒設定或為空值,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt 。 (非空值時不作处理)
$ ${file?my.file.txt} #若 $file 沒設定,則將 my.file.txt 輸出至 STDERR。 (空值及非空值時不作处理)
$ ${file:?my.file.txt} #若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值時不作处理)
$ ${#var} #返回变量值的长度

函数

[ function ] funname [()]
{
    action;
    [return int;]
}

funWithParam(){
    echo $1
}
funWithParam 33
结果输出:33


常用的位置参数如下:

$0                 					  相当于 C 语言的 main 函数的 argv[0]
$1$2$3....    					  这些称为位置参数,相当于 C 语言的 main 函数里面的 argv[1]、argv[2].....
$#                					  相当于 C 语言里面的 main 函数的 argc -1 ,注意这里的 # 后面不表示任何注释
$@                                     表示参数列表 "$1","$2",.......... ,例如可以在 for 循环 的 in 后面
$* 表示参数列表 “$1”,"$2",...........   同上。不过这两个表示法有点区别:$@$*的存储方式不同,$@ 是按每个参数分开(分块)存储的;而, $* 是连续存储在一个块里面
$?                                    上一条命令的  Exit Status
$$                                    当前进程号
shift                                 左移命令(比如 shift 3 ,表示原来的 $4 变成 $1,原来的 $5 变成 $2 ,原来的 $1$2,$3 丢弃,$0不移动。不带参的 shift 命令相当于 shift 1)。

history
$ history #历史执行过的所有命令
$ history 3 #最近3条
$ history -w #将当前shell的历史记录写入~/.bash_history
$ history -c #清除当前shell的history
$ !3 #执行~/.bash_history中第3条命令
$ !! #执行上一条
$ !his #执行从后往前找到第一条以his为前缀的命令,找不到则not found
命令执行判断 && ||
$ ls /a && touch /a/b  #当前面命令执行正确的时候才会执行后面的
$ ls /a || mkdir /a  #当前面命令执行错误的时候才会执行后面的

#常用操作
$ ls /a && touch /a/b || touch /a/c
$ test -e ./t.sh && echo "y" || echo "n" #查看文件是否存在
cut、grep

cut缺点:难以处理多空格相连的数据

echo $PATH | cut -d ':' -f 3
#-d后面接分分隔符   -f后面写获取第几段

$ a=123456
$ echo $a |cut -c 3-  #-c  cut范围
3456
$ echo $a |cut -c 3-4
34


$ ll |grep -v '33' #将不包含33字符串的行取出
grep -i 忽略大小写
grep -c 输出匹配到的次数
grep [a-zA-Z] 输出非空行
sort、uniq、wc
sort
-f 忽略大小写差异
-b 忽略每行前面空格
-M 已月份名字排序
-n 使用纯数字排序(默认按照文字类型排序)
-r 反向排序
-t 分隔符号(默认为tab)
-k n 按照第n个字段排序

#-n
$ sort
1
11
2
$ sort -n
1
2
11

#-t -k
$ cat /etc/passwd | sort -t ':' -k 3 #按照以:分隔的第三栏 排序
root:x:0:0:root:/root:/bin/bash
tony:x:1000:1000:tony,,,:/home/tony:/bin/csh
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
uniq #重复的数据只输出一次
uniq -i #忽略大小写
uniq -c #count,还输出出现的次数
wc #会输出 行数、字数、字符数
wc -l #只输出行数
wc -w #只输出字数
wc -m/-c #只输出字符
字符转换 文件处理 tr、col、join、paste、expand
tr -d 'xx' #删除其中所有xx字符串
tr -s 'xx' 'aa' #将所有xx替换成aa

$ cat /etc/passwd | tr -d ':'
$ last |tr =s '[a-z]' '[A-Z]'
$ cat filename | tr -d '\r' > newfile #可以将DOS文件尾部的^M(\r)去掉
col -x #将tab换成空格

expand -t 2 #将tab用两个空格替换(默认为8)
join -t ':' #join默认以空格为分隔符,此处以:为分隔符,并且默认比较第一个字段的字符,如果相同则连接成一行。
join -i #忽略大小写差异
join -1 3 #第一个文件用第三个字段来比较
join -2 2 #第二个文件用第二个字段来比较

join -t ':' -1 4 /etc/passwd -2 3 /etc/group
paste #连接两个文件的行,默认tab分隔
paste -d '?' #以?分隔
paste file1 file2 #如果file1或file2是'-',则表示来自stdin的数据

paste -d '!'  - hh > hh1 

文件拆分split

$ split -l 10 #根据每10行拆分
$ split -b 300k #划分成每300k一个文件

$ split -b 300k /etc/termcap termcap
$ ls
termcapaa
termcapab
termcapac
...
$ cat termcap* >> termcap

$ ll | split -l 10 - hh #将stdin拆分成每10行存入hhaa,hhab .....
参数替换xargs

xargs命令通俗来讲就是将标准输入转成各种格式化的参数,所以命令[command 1] | xargs [command 2]就是将command 1的标准输出结果,通过管道|变成xargs的标准输入,然后xargs再将此标准输入变成参数,传给[command 2]。这样一来,通过xargs命令,我们便可以在管道后面使用那些不接收标准输入的命令了

$ ls | xargs ls -al #输出各目录的子目录的详细信息。ls后将输出传到xargs,处理后成为一个个参数,传给后面的ls

-e eof-str
设置“文件结束符”,xargs 在处理标准输入时,如果遇到“文件结束符”,则其后的所有输入都将被忽略。如果 -E 和 -e 选项都没有被使用,则表示在标准输入中没有字符会被当成“文件结束符”处理。
$ echo "\% 33 \%"|xargs -E'33' echo #注意-E后面没有空格
%
$ echo "\% 33 \%"|xargs echo
% 33 %

-0 :当 xargs 使用此选项时,null字符会被作为“数据块”的分隔符,而引号(单引用和双引号)都不在具有特殊含义(所有的字符都代表他们自己);文件结束符(EOF)也将失效。通常情况下,当“数据块”中包含空格、引号、反斜杠时适合使用此选项
$ echo "\' \%"|xargs echo
' %
$ echo "\' \%"|xargs -0 echo
\' \%

-p:执行每个命令的参数都会i询问y/n
-n 3:将输入分成每3个一份作为参数

Shell脚本练习

循环日期创建文件

#!/bin/bash

read a
filename=${a:-filename} #避免不输入直接回车

for ((i = 1; i <= 10; i++))
do
        date=`date --date="$i days ago" +%Y%m%d`
        file="$filename""_""$date"
        touch $file
done

exit 0
判断符[]

注意[ ]必须和内容隔开,等号两边也有空格

[ str1 == str2 ]    当两个串有相同内容、长度时为真 
[ str1 != str2 ]    当串str1和str2不等时为真 
[ -n str1 ]       当串的长度大于0时为真(串非空) 
[ -z str1 ]       当串的长度为0时为真(空串) 
[ str1 ]         当串str1为非空时为真
判断
if [xxx]; then
	xx
else
	aa
fi

if [ "$1" == "22" ]; then
        echo "66"
elif [ "$1" == "33" ]; then
        echo "77"
else
        echo "hh"
fi
case $1 in
	"hello")
		echo "hh"
		;;
	"")
		echo "null"
		;;
	*)
		echo "..."
		;;
esac
函数
function gg(){
	echo "hhh $1 $2 $3";
    return $4;
}

gg 3 4 5 11
echo $?


#输出:
hhh 3 4 5
11
循环
while [ xx ]
do
	echo "!"
done

#和while相反,直到xx为真,退出
until [ xx ]
do
	echo "!"
done

for (( i=0; i<100; i++))
do
	echo $i
done

for i in 0 1 3
do
	echo $i
done
#0 1 3 
调试 sh
sh -n t.sh #不执行,检查语法。正确则无输出
sh -v t.sh #打印脚本内容,再执行
sh -x t.sh #一行一行交替打印脚本执行的代码和输出(如果是执行的代码会在输出前面有个+)

#t.sh
ech1=echi1
for i in 0 1 2
do
        echo $i
done

$ sh -x t.sh
#输出
+ ech1=echi1
+ echo 0
0
+ echo 1
1
+ echo 2
2
+ exit 0
以空格为分隔符分割文件内容并输出
awk -F: #以:分割
$ awk  '{for(i=1;i<=NF;i++){print $i}}' filename

LeetCode刷题

第十行 https://leetcode-cn.com/problems/tenth-line/

tail -n +10 file.txt|head -n 1

有效电话号码 https://leetcode-cn.com/problems/valid-phone-numbers/

egrep "(^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$)|(^[0-9]{3}-[0-9]{3}-[0-9]{4}$)" file.txt

转置文件 https://leetcode-cn.com/problems/transpose-file/

awk '
{
    for (i=1; i<=NF; i++) {
        if (NR==1) {
            res[i]=$i
        } else { #NR>=2
            res[i]=res[i] " " $i
        }
    }
}
END {
    for (i=1; i<=NF; i++) {
        print res[i]
    }
}
' file.txt 

统计词频 https://leetcode-cn.com/problems/word-frequency/

awk '
{
    for(i=1; i<=NF; i++){
        res[$i]+=1
    }
}
END{
    for(k in res){
        print k " " res[k]
    }
}
' words.txt | sort -rn -k 2
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值