shell技巧

/ Linux / 没有评论 / 2188浏览

shell支持正则:Linux shell判断字符串是否以某些字符开头

==比较

使用bash检查字符串是否以某些字符开头可以使用==比较

[[ $str == h* ]]

示例

str="hello"
if [[ $str == h* ]];
then
 echo 'yes'
fi

有两个地方需要注意:

  1. h*不需要使用引号括起来,使用引号括起来是直接做相等比较
  2. 比较语句使用双中括号括起来,而不是使用单中括号

=~正则比较

如果使用Bash的正则

str="hello"
if [[ "$str" =~ ^he.* ]]; then
    echo "yes"
fi

使用正则匹配字符串的开头字符需要注意:

shell去掉最后一个字符

387691,387710,387720,387817,387922,388067, 如何搞掉最后一个,? 简单快捷的?

sed 's/.$//'
awk '{sub(/.$/,"")}1'
awk '{printf $0"\b \n"}' ufile

linux去除首个字符或最后一个字符

在linux下的shell操作,有一些业务需求,将输入的连接做个简单处理,比如去除链接后边的“/”,或者是获取到svn版本号为‘r128137’,想把第一个字符去掉,保留有用的数字。那么linux是如何实现的呢?当然,方法有很多种,适合自己是关键,这里只举一例:去除链接后边的“/”

apk_path='https://www.cnblogs.com/hulk-1029/'
echo ${apk_path%?}

去除字符串a123456首个字符

echo a123456 | awk '{print substr($1,2)}'

Linux如何查找大文件

find . -type f -size +800M

如上命令所示,我们仅仅能看到超过800M大小的文件的文件名称,但是对文件的信息(例如,文件大小、文件属性)一无所知,那么能否更详细显示一些文件属性或信息呢,当然可以,如下所示

find . -type f -size +800M  -print0 | xargs -0 ls -l
当我们只需要查找超过800M大小文件,并显示查找出来文件的具体大小,可以使用下面命令
find . -type f -size +800M  -print0 | xargs -0 du -h
如果你还需要对查找结果按照文件大小做一个排序,那么可以使用下面命令
find . -type f -size +800M  -print0 | xargs -0 du -h | sort -nr

awk中如何用print输出单引号'

awk '{print " '\'' "}'

其中: ''' 这三个' 都是单引号

Linux shell 提取文件名和目录名

${}用于字符串的读取,提取和替换功能,可以使用${} 提取字符串

  1. 提取文件名
 var=/dir1/dir2/file.txt
echo ${var##*/}

结果:

file.txt
  1. 提取后缀
echo ${var##*.}

结果:

txt
  1. 提取不带后缀的文件名,分两步
tmp=${var##*/}
echo $tmp
echo ${tmp%.*}

结果:

file.txt
file
  1. 提取目录
echo ${var%/*}

结果:

/dir1/dir2
  1. 使用文件目录的专有命令提取文件名,注意:basename是一个命令,使用$(), 而不是​${}
echo $(basename $var)

结果:

file.txt
  1. 提取不带后缀的文件名
 echo $(basename  $var .txt)

结果:

file
  1. 提取目录
dirname $var
echo $(dirname $var)

结果:

/dir1/dir2
/dir1/dir2

shell 获取当前目录下的jar文件

1、示例

function getDir() {
    for item in `ls $1`
    do
    fileName=$1"/"$item
    if [ -d $fileName ]
    then
        echo $fileName"是目录"
        #getDir $fileName
    else
        echo $fileName"不是目录"
        echoFile $fileName
    fi
    done
}

function echoFile() {
    fileName=$1
    echo ${fileName##*.}
    if [ ! ${fileName##*.} = jar ]
    then
      echo $1"不是jar包"
    else 
      echo $1"是jar包"
    fi
}

#在当前目录下查找sh脚本
for name in `find . -name *.sh`
do
    echo ">>>>>>>>>>>>>>>$name" 
    if [ "${name##*.}"x = "sh"x ]
    then
    echo "是脚本"
    fi
done 

dir="/home/fjw"
getDir $dir

2、附注

给定路径:

path=/home/test.tar.gz 
echo ${path%/*} # 结果为/home 等效 dirname path
echo ${path##*/} # 结果为test.tar.gz 等效basename path

文件

file=${path##*/} # file为test.tar.gz
echo ${FILE%%.*} # 结果为test
echo ${FILE%.*} # 结果为test.tar
echo ${FILE##*.} # 结果为gz
echo ${FILE#*.} # 结果为tar.gz

说明:

取目录部分:${path%/*} (类似 dirname " $path") 取文件名称:file=${path##*/}(类似basename " $path") 取最短基本名称:${file%%.*} 取最长基本名称:${file%.*} 取最短扩展名:${file##*.} 或者 ${path##*.} 取最长扩展名:${file#*.} 或者 ${path#*.}

关于shell脚本时遇value too great for base (error token is "08")

今天在书写一个定时cp脚本时遇到了一个问题,value too great for base (error token is "08"),在网上查看到原来是以0开头的数字 系统会默认识别为八进制数,所以我的 $datem-1这样的获取上个月的月份是回报:value too great for base (error token is "08")这个错误的,解决办法就是: 将$datem格式或者声明称十进制,`10#$datem`-1 这样就可以了。 也就是将要转换成十进制的变量或者数字 在前面加上`10#`即可:

给出我的代码:

[root@morp shell]# cat backwebdb.sh 
#!/bin/bash
#admin fengtaotao Email:23956580@qq.com
#Fri Jul  3 16:35:48 CST 2015
pathh=/web/www/morp/musicFile/
pathd=/opt2/musicFile/
datem=`date +%m`

if [ "$datem" == 01 ] ;then
        datem="_12"
        datey=`date +%Y`
        datey=$(($datey-1))
else   
        datem="$((10#$datem-1))"
#       datey=`date +%Y`
        echo $datem
fi
echo $datey
#echo $datem

#dird="$datey$datem"
#readd=`date +%N`.txt
#find $pathh -name $dird &>> $readd
#for i in $(cat $readd);do
#       aac=$(echo $i | awk -F "/" '{print $6"/"$7"/"}')
#       aac=${pathd}${aac}
#       cp -r $i $aac &>>dbcp.log
#done

#rm -rf $readd

OK这样问题就解决了,然后将没有执行备份的重新执行,由于我这个脚本时用find获取信息的所以对系统资源的消耗比较大,当然大家如果需要备份的目录不变的话就可以直接读取一个路径文档,可以较少对系统的消耗!

日期 date +%F-%T-%N

date +%F-%T-%N

shell获取时间戳

#明天凌晨 对应的毫秒时间戳
tomorrow=`date -d next-day +%Y-%m-%d`
timeStamp=`date -d "$tomorrow 00:00:00" +%s`
currentTimeStamp=$(($timeStamp*1000+10#`date "+%N"`/1000000)) #将current转换为时间戳,精确到毫秒
echo $currentTimeStamp
 
#当前时间 对应的毫秒时间戳
current=`date "+%Y-%m-%d %H:%M:%S"`
timeStamp=`date -d "$current" +%s` 
currentTimeStamp=$((timeStamp*1000+10#`date "+%N"`/1000000)) #将current转换为时间戳,精确到毫秒
echo $currentTimeStamp
 
#当前时间 对应的秒时间戳
current=`date "+%Y-%m-%d %H:%M:%S"`
timeStamp=`date -d "$current" +%s` 
currentTimeStamp=$(((timeStamp*1000+10#`date "+%N"`/1000000)/1000)) #将current转换为时间戳,精确到秒
echo $currentTimeStamp

linux shell 中判断字符串为空的正确方法

#!/bin/sh
STRING=
if [ -z "$STRING" ]; then
    echo "STRING is empty"
fi
if [ -n "$STRING" ]; then
    echo "STRING is not empty"
fi

执行:

root@james-desktop:~# ./zerostring.sh
STRING is empty
#!/bin/sh
STRING=
if [ -z $STRING ]; then
    echo "STRING is empty"
fi
if [ -n $STRING ]; then
    echo "STRING is not empty"
fi 

输出错误结果:

root@james-desktop:~# ./zerostring.sh
STRING is empty
STRING is not empty

shell 中的条件判断 “并且” “或者”

  1. 并且,条件 c1并且条件c2
if [ c1 -a c2 ]; then
…
fi
if [ c1 ] && [ c2 ]; then
…
fi
  1. 或者,条件 c1或者 条件c2
if [ c1 -o c2 ]; then
…
fi
if [ c1 ] || [  c2 ]; then
…
fi

例如

a=0
b=1
if [ $a = 1 ] || [ $b = 1 ]; then
	echo "good"
fi