您的位置:首页 > 运维架构 > Shell

linux 文件,字符,shell基本操作

2015-08-06 11:29 711 查看
最近打算开始写点shell脚本,主要涉及到日志读取处理及文件的操作,感觉挺简单,但是还有很多方法没有掌握,还得查点资料,现在把需要涉及到的知识做个记录吧。

cut:

cut是一个选取命令,就是将一段数据经过分析,取出我们想要的。一般来说,选取信息通常是针对“行”来进行分析的,并不是整篇信息分析的.

语法格式为:

cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file]

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。

-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。

-c :以字符为单位进行分割。

-d :自定义分隔符,默认为制表符。

-f :与-d一起使用,指定显示哪个区域。

-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除。

在这里可以用-d自定义符号来读取日志分段

sed

sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作,下面先了解一下sed的用法

sed命令行格式为:

sed [-nefri] ‘command’ 输入文本

-n∶使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到萤幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

-e∶直接在指令列模式上进行 sed 的动作编辑;

-f∶直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作;

-r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)

-i∶直接修改读取的档案内容,而不是由萤幕输出。

常用命令:

a ∶新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~

c ∶取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!

d ∶删除,因为是删除啊,所以 d 后面通常不接任何咚咚;

i ∶插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

p ∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~

s ∶取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

举例:(假设我们有一文件名为ab)

删除某行
[root@localhost ruby] # sed '1d' ab #删除第一行 
[root@localhost ruby] # sed '$d' ab #删除最后一行
[root@localhost ruby] # sed '1,2d' ab #删除第一行到第二行
[root@localhost ruby] # sed '2,$d' ab #删除第二行到最后一行

  显示某行
. [root@localhost ruby] # sed -n '1p' ab #显示第一行 
[root@localhost ruby] # sed -n '$p' ab #显示最后一行
[root@localhost ruby] # sed -n '1,2p' ab #显示第一行到第二行
[root@localhost ruby] # sed -n '2,$p' ab #显示第二行到最后一行

 使用模式进行查询
[root@localhost ruby] # sed -n '/ruby/p' ab #查询包括关键字ruby所在所有行
[root@localhost ruby] # sed -n '/\$/p' ab #查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含义

  增加一行或多行字符串
[root@localhost ruby]# cat ab
Hello!
ruby is me,welcome to my blog.
end
[root@localhost ruby] # sed '1a drink tea' ab #第一行后增加字符串"drink tea"
Hello!
drink tea
ruby is me,welcome to my blog. 
end
[root@localhost ruby] # sed '1,3a drink tea' ab #第一行到第三行后增加字符串"drink tea"
Hello!
drink tea
ruby is me,welcome to my blog.
drink tea
end
drink tea
[root@localhost ruby] # sed '1a drink tea\nor coffee' ab #第一行后增加多行,使用换行符\n
Hello!
drink tea
or coffee
ruby is me,welcome to my blog.
end

  代替一行或多行
[root@localhost ruby] # sed '1c Hi' ab #第一行代替为Hi
Hi
ruby is me,welcome to my blog.
end
[root@localhost ruby] # sed '1,2c Hi' ab #第一行到第二行代替为Hi
Hi
end


  替换一行中的某部分

sort

sort命令是帮我们依据不同的数据类型进行排序,其语法及常用参数格式:

  sort [-bcfMnrtk][源文件][-o 输出文件]

补充说明:sort可针对文本文件的内容,以行为单位来排序。

参  数:

-b 忽略每行前面开始出的空格字符。

-c 检查文件是否已经按照顺序排序。

-f 排序时,忽略大小写字母。

-M 将前面3个字母依照月份的缩写进行排序。

-n 依照数值的大小排序。

-o<输出文件> 将排序后的结果存入指定的文件。

-r 以相反的顺序来排序。

-t<分隔字符> 指定排序时所用的栏位分隔字符。

-k 选择以哪个区间进行排序。

shell注释-->

A、方法一

  :<<BLOCK'

  ....注释内容

'BLOCK

  B、方法二

  :<<'BLOCK

  ....注释内容

  BLOCK'

  C、方法三

  :<<'

....注释内容

'

  以上三种方法都是通过在:<

  

  BLOCK为Here Documents中的定义符号可以随意起名,只要前后匹配就行了

更帅的方法:

cat <<"EOF" > /dev/null
    this
    is
    a
    multi-
    line
    comment
    EOF
或者:
: cat <<"EOF"
    this
    is
    a
    multi-
    line
    comment
    EOF
<--shell注释

Grep

grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来。grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

2.格式

grep [options]

3.主要参数

[options]主要参数:

-c:只输出匹配行的计数。

-I:不区分大 小写(只适用于单字符)。

-h:查询多文件时不显示文件名。

-l:查询多文件时只输出包含匹配字符的文件名。

-n:显示匹配行及 行号。

-s:不显示不存在或无匹配文本的错误信息。

-v:显示不包含匹配文本的所有行。

pattern正则表达式主要参数:

\: 忽略正则表达式中特殊字符的原有含义。

^:匹配正则表达式的开始行。

$: 匹配正则表达式的结束行。

\<:从匹配正则表达 式的行开始。

\>:到匹配正则表达式的行结束。

[ ]:单个字符,如[A]即A符合要求 。

[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。

。:所有的单个字符。

* :有字符,长度可以为0。

4.grep命令使用简单实例

$ grep ‘test’ d*

显示所有以d开头的文件中包含 test的行。

$ grep ‘test’ aa bb cc

显示在aa,bb,cc文件中匹配test的行。

$ grep ‘[a-z]\{5\}’ aa

显示所有包含每个字符串至少有5个连续小写字符的字符串的行。

$ grep ‘w\(es\)t.*\1′ aa

如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着 另外一个es(\1),找到就显示该行。如果用egrep或grep -E,就不用”\”号进行转义,直接写成’w(es)t.*\1′就可以了。

5.grep命令使用复杂实例

假设您正在’/usr/src/Linux/Doc’目录下搜索带字符 串’magic’的文件:

$ grep magic /usr/src/Linux/Doc/*

sysrq.txt:* How do I enable the magic SysRQ key?

sysrq.txt:* How do I use the magic SysRQ key?

其中文件’sysrp.txt’包含该字符串,讨论的是 SysRQ 的功能。

默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:

grep: sound: Is a directory

这可能会使’grep’ 的输出难于阅读。这里有两种解决的办法:

明确要求搜索子目录:grep -r

或忽略子目录:grep -d skip

如果有很多 输出时,您可以通过管道将其转到’less’上阅读:

$ grep magic /usr/src/Linux/Documentation/* | less

这样,您就可以更方便地阅读。
还想到一个使用搜索文件的办法
aa=$(find file)
cp $aa /home
rm $aa


test

-b filename当filename 存在并且是块文件时返回真(返回0)
-c filename当filename 存在并且是字符文件时返回真
-d pathname当pathname 存在并且是一个目录时返回真
-e pathname当由pathname 指定的文件或目录存在时返回真
-f filename当filename 存在并且是正规文件时返回真
-g pathname当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真
-h filename当filename 存在并且是符号链接文件时返回真 (或 -L filename)
-k pathname当由pathname 指定的文件或目录存在并且设置了"粘滞"位时返回真
-p filename当filename 存在并且是命名管道时返回真
-r pathname当由pathname 指定的文件或目录存在并且可读时返回真
-s filename当filename 存在并且文件大小大于0 时返回真
-S filename当filename 存在并且是socket 时返回真
-t fd当fd 是与终端设备相关联的文件描述符时返回真
-u pathname当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真
-w pathname当由pathname 指定的文件或目录存在并且可写时返回真
-x pathname当由pathname 指定的文件或目录存在并且可执行时返回真
-O pathname当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写)
-G pathname当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真
file1 -nt file2file1 比file2 新时返回真
file1 -ot file2file1 比file2 旧时返回真
f1 -ef f2files f1 and f2 are hard links to the same file
举例: if [ -b /dev/hda ] ;then echo "yes" ;else echo "no";fi // 将打印 yes
test -c /dev/hda ; echo $? // 将打印 1 表示test 命令的返回值为1,/dev/hda 不是字符设备
[ -w /etc/passwd ]; echo $? // 查看对当前用户而言,passwd 文件是否可写


测试时逻辑操作符

-a逻辑与,操作符两边均为真,结果为真,否则为假。
-o逻辑或,操作符两边一边为真,结果为真,否则为假。
!逻辑否,条件为假,结果为真。
举例: [ -w result.txt -a -w score.txt ] ;echo $? // 测试两个文件是否均可写


常见字符串测试

-z string字符串string 为空串(长度为0)时返回真
-n string字符串string 为非空串时返回真
str1 = str2字符串str1 和字符串str2 相等时返回真
str1 == str2同 =
str1 != str2字符串str1 和字符串str2 不相等时返回真
str1 < str2按字典顺序排序,字符串str1 在字符串str2 之前
str1 > str2按字典顺序排序,字符串str1 在字符串str2 之后
举例: name="zqf"; [ $name = "zqf" ];echo $? // 打印 0 表示变量name 的值和字符串"zqf"相等


常见数值测试

int1 -eq int2如果int1 等于int2,则返回真
int1 -ne int2如果int1 不等于int2,则返回真
int1 -lt int2如果int1 小于int2,则返回真
int1 -le int2如果int1 小于等于int2,则返回真
int1 -gt int2如果int1 大于int2,则返回真
int1 -ge int2如果int1 大于等于int2,则返回真
在 (()) 中的测试:
<小于(在双括号里使用)(("$a" < "$b"))
<=小于等于 (在双括号里使用)(("$a" <= "$b"))
>大于 (在双括号里使用)(("$a" > "$b"))
>=大于等于(在双括号里使用)(("$a" >= "$b"))
举例: x=1 ; [ $x -eq 1 ] ; echo $? // 将打印 0 表示变量x 的值等于数字1 x=a ; [ $x -eq "1" ] // shell 打印错误信息 [: a: integer expression expected

test , [] , [[]]

因为 shell 和我们通常编程语言不同,更多的情况是和它交互,总是调用别人。 所以有些本属于程序语言本身的概念在 shell 中会难以理解。"基本功" 不好, 更容易 "犯困" 了,我就是一个 :-) 。
以 bash 为例 (其他兼容 shell 差不多):

test 和 [ 是 bash 的内部命令,GNU/linux 系统的 coreutils 软件包通 常也带 /usr/bin/test 和 /usr/bin/[ 命令。如果我们不用绝对路径指 明,通常我们用的都是 bash 自带的命令。
[[ 是 bash 程序语言的关键字!

$ ls -l /usr/bin/[ /usr/bin/test
-rwxr-xr-x 1 root root 37400  9月 18 15:25 /usr/bin/[
-rwxr-xr-x 1 root root 33920  9月 18 15:25 /usr/bin/test
$ type [ [[ test
[ is a shell builtin
[[ is a shell keyword
test is a shell builtin

绝大多数情况下,这个三个功能通用。但是命令和关键字总是有区别的。命令和 关键字的差别有多大呢?
如果是命令,它就和参数组合为一体被 shell 解释,那样比如 ">" "<" 就被 shell 解释为重定向符号了。关键字却不这样。


[[ 中使用 && 和 ||在

[ 中使用 -a 和 -o 表示逻辑与和逻辑或。




[[ 中可以使用通配符

arch=i486
[[ $arch = i*86 ]] && echo "arch is x86!"




[[ 中匹配字符串或通配符,不需要引号

[[ $arch_com = i386 || $ARCH = i*86 ]] &&
    cat >> $TFS_REPO <<EOF
[tfs-i386]
name=GTES11.3 prelim1
baseurl=${BASEURL}i386/
enabled=1
EO

shell 判断变量为数字

方法1:通过expr 计算变量与一个整数值相加,如果能正常执行则为整数,否则执行出错,$?将是非0的值

expr $args + 0 &>/dev/null

方法2:打印变量通过sed替换的方式,将变量中的数字替换为空,如果执行替换后变量为空,则为整数

echo $args | sed 's/[0-9]//g'

如果判断负数则再用sed过滤负号

echo $args | sed 's/[0-9]//g' | sed 's/-//g'

下面的脚本通过两个函数来实现数值判断。代码很简单,就不加注释了。

#!/bin/bash 
usage(){ 
cat <<EOF 
USEAGE:sh $0 args1 args2 
exit 1
EOF 
} 
checkInt(){ 
expr $1 + 0 &>/dev/null
[ $? -ne 0 ] && { echo "Args must be integer!";exit 1; } 
} 
checkInt1(){ 
tmp=`echo $1 |sed 's/[0-9]//g'` 
[ -n "${tmp}" ]&& { echo "Args must be integer!";exit 1; } 
} 
[ $# -ne 2 ]&&usage 
args1=$1
args2=$2
checkInt $args1 
checkInt1 $args2 
if [ $args1 -gt $args2 ];then 
echo "yes,$args1 greate than $args2"
else
echo "no,$args1 less than $args2"
fi

数值比较:

n1 -eq n2检查n1是否等于n2 n1 -le n2检查n1是否小于等于n2

n1 -ge n2检查n1是否大于等于n2 n1 -lt n2检查n1是否小于n2

n1 -gt n2检查n1是否大于n2 n1 -ne n2检查n1是否不等于n2

推出状态码退出。

if test condition
then 
commands
fi


字符串比较:

str1 == str2检查str1与str2是否相同 str1 > str2检查str1是否大于str2

str1 != str2检查str1与str2是否不同 -n str1 检查str1的长度是否大于0

str1 < str2检查str1是否小于str2 -z str1 检查str1的长度是否为0

字符串顺序:

*大于和小于符号一定要转义,否则shell会将他们当做重定向符号,将字符串值看作是文件名。

*大于和小于顺序与在sort中不同

*test使用标准的ASCII排序,使用每个字母的ASCII数值来决定排序顺序,sort命令使用为当前系统语言设置定义的排序顺序。对于英语来说,当前设置指定小写字母排在大写字母之前。

cp

也就是copy命令
cp(选项)(参数)

-a:此参数的效果和同时指定"-dpR"参数相同;
-d:当复制符号连接时,把目标文件或目录也建立为符号连接,并指向与源文件或目录连接的原始文件或目录;
-f:强行复制文件或目录,不论目标文件或目录是否已存在;
-i:覆盖既有文件之前先询问用户;
-l:对源文件建立硬连接,而非复制文件;
-p:保留源文件或目录的属性;
-R/r:递归处理,将指定目录下的所有文件与子目录一并处理;
-s:对源文件建立符号连接,而非复制文件;
-u:使用这项参数后只会在源文件的更改时间较目标文件更新时或是名称相互对应的目标文件并不存在时,才复制文件;
-S:在备份文件时,用指定的后缀“SUFFIX”代替文件的默认后缀;
-b:覆盖已存在的文件目标前将目标文件备份;
-v:详细显示命令执行的操作。

源文件:制定源文件列表。默认情况下,cp命令不能复制目录,如果要复制目录,则必须使用-R选项;
目标文件:指定目标文件。当“源文件”为多个文件时,要求“目标文件”为指定的目录

注意事项:

如果把一个文件复制到一个目标文件中,而目标文件已经存在,那么,该目标文件的内容将被破坏。
此命令中所有参数既可以是绝对路径名,也可以是相对路径名。
通常会用到点.或点点..的形式。例如,下面的命令将指定文件复制到当前目录下:

cp ../mary/homework/assign .


所有目标文件指定的目录必须是己经存在的,cp命令不能创建目录。如果没有文件复制的权限,则系统会显示出错信息。
将文件file复制到目录/usr/men/tmp下,并改名为file1

cp file /usr/men/tmp/file1


将目录/usr/men下的所有文件及其子目录复制到目录/usr/zh中

cp -r /usr/men /usr/zh


交互式地将目录/usr/men中的以m打头的所有.c文件复制到目录/usr/zh中

cp -i /usr/men m*.c /usr/zh


我们在Linux下使用cp命令复制文件时候,有时候会需要覆盖一些同名文件,覆盖文件的时候都会有提示:需要不停的按Y来确定执行覆盖。文件数量不多还好,但是要是几百个估计按Y都要吐血了,于是折腾来半天总结了一个方法:

cp aaa/* /bbb 
复制目录aaa下所有到/bbb目录下,这时如果/bbb目录下有和aaa同名的文件,需要按Y来确认并且会略过aaa目录下的子目录。 

cp -r aaa/* /bbb
这次依然需要按Y来确认操作,但是没有忽略子目录。

cp -r -a aaa/* /bbb 
依然需要按Y来确认操作,并且把aaa目录以及子目录和文件属性也传递到了/bbb。

\cp -r -a aaa/* /bbb 
成功,没有提示按Y、传递了目录属性、没有略过目录。


du

du命令是查看使用空间的

1.命令格式:

du [选项][文件]

2.命令功能:

显示每个文件和目录的磁盘使用空间。

3.命令参数:

-a或-all 显示目录中个别文件的大小。

-b或-bytes 显示目录或文件大小时,以byte为单位。

-c或--total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。

-k或--kilobytes 以KB(1024bytes)为单位输出。

-m或--megabytes 以MB为单位输出。

-s或--summarize 仅显示总计,只列出最后加总的值。

-h或--human-readable 以K,M,G为单位,提高信息的可读性。

-x或--one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。

-L<符号链接>或--dereference<符号链接> 显示选项中所指定符号链接的源文件大小。

-S或--separate-dirs 显示个别目录的大小时,并不含其子目录的大小。

-X<文件>或--exclude-from=<文件> 在<文件>指定目录或文件。

--exclude=<目录或文件> 略过指定的目录或文件。

-D或--dereference-args 显示指定符号链接的源文件大小。

-H或--si 与-h参数相同,但是K,M,G是以1000为换算单位。

-l或--count-links 重复计算硬件链接的文件。

tar

tar [-cxtzjvfpPN] 文件与目录 ....

参数:

-c :建立一个压缩文件的参数指令(create 的意思);

-x :解开一个压缩文件的参数指令!

-t :查看 tarfile 里面的文件!

特别注意,在参数的下达中, c/x/t 仅能存在一个!不可同时存在!

因为不可能同时压缩与解压缩。

-z :是否同时具有 gzip 的属性?亦即是否需要用 gzip 压缩?

-j :是否同时具有 bzip2 的属性?亦即是否需要用 bzip2 压缩?

-v :压缩的过程中显示文件!这个常用,但不建议用在背景执行过程!

-f :使用档名,请留意,在 f 之后要立即接档名喔!不要再加参数!

   例如使用『 tar -zcvfP tfile sfile』就是错误的写法,要写成

   『 tar -zcvPf tfile sfile』才对喔!

-p :使用原文件的原来属性(属性不会依据使用者而变)

-P :可以使用绝对路径来压缩!

-N :比后面接的日期(yyyy/mm/dd)还要新的才会被打包进新建的文件中!

--exclude FILE:在压缩的过程中,不要将 FILE 打包!

范例:

范例一:将整个 /etc 目录下的文件全部打包成为 /tmp/etc.tar

[root@linux ~]# tar -cvf /tmp/etc.tar /etc <==仅打包,不压缩!

[root@linux ~]# tar -zcvf /tmp/etc.tar.gz /etc <==打包后,以 gzip 压缩

[root@linux ~]# tar -jcvf /tmp/etc.tar.bz2 /etc <==打包后,以 bzip2 压缩

# 特别注意,在参数 f 之后的文件档名是自己取的,我们习惯上都用 .tar 来作为辨识。

# 如果加 z 参数,则以 .tar.gz 或 .tgz 来代表 gzip 压缩过的 tar file ~

# 如果加 j 参数,则以 .tar.bz2 来作为附档名啊~

# 上述指令在执行的时候,会显示一个警告讯息:

# 『tar: Removing leading `/' from member names』那是关於绝对路径的特殊设定。

范例二:查阅上述 /tmp/etc.tar.gz 文件内有哪些文件?

[root@linux ~]# tar -ztvf /tmp/etc.tar.gz

# 由於我们使用 gzip 压缩,所以要查阅该 tar file 内的文件时,

# 就得要加上 z 这个参数了!这很重要的!

范例三:将 /tmp/etc.tar.gz 文件解压缩在 /usr/local/src 底下

[root@linux ~]# cd /usr/local/src

[root@linux src]# tar -zxvf /tmp/etc.tar.gz

# 在预设的情况下,我们可以将压缩档在任何地方解开的!以这个范例来说,

# 我先将工作目录变换到 /usr/local/src 底下,并且解开 /tmp/etc.tar.gz ,

# 则解开的目录会在 /usr/local/src/etc 呢!另外,如果您进入 /usr/local/src/etc

# 则会发现,该目录下的文件属性与 /etc/ 可能会有所不同喔!

范例四:在 /tmp 底下,我只想要将 /tmp/etc.tar.gz 内的 etc/passwd 解开而已

[root@linux ~]# cd /tmp

[root@linux tmp]# tar -zxvf /tmp/etc.tar.gz etc/passwd

# 我可以透过 tar -ztvf 来查阅 tarfile 内的文件名称,如果单只要一个文件,

# 就可以透过这个方式来下达!注意到! etc.tar.gz 内的根目录 / 是被拿掉了!

范例五:将 /etc/ 内的所有文件备份下来,并且保存其权限!

[root@linux ~]# tar -zxvpf /tmp/etc.tar.gz /etc

# 这个 -p 的属性是很重要的,尤其是当您要保留原本文件的属性时!

范例六:在 /home 当中,比 2005/06/01 新的文件才备份

[root@linux ~]# tar -N '2005/06/01' -zcvf home.tar.gz /home

范例七:我要备份 /home, /etc ,但不要 /home/dmtsai

[root@linux ~]# tar --exclude /home/dmtsai -zcvf myfile.tar.gz /home/* /etc

范例八:将 /etc/ 打包后直接解开在 /tmp 底下,而不产生文件!

[root@linux ~]# cd /tmp

[root@linux tmp]# tar -cvf - /etc | tar -xvf -
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: