• linux中经常要对一些动态的文本文件抽取指定的字符串,比如执行ps命令后想要获取指定的运行进程(如ps自己)的PID号(同一个进程每次启动的时候pid号是随机分配的)。该怎么办呢?当然,可以用一些截取字符串的方法...

    在linux中经常要对一些动态的文本文件抽取指定的字符串,比如执行ps命令后想要获取指定的运行进程(如ps自己)的PID号(同一个进程每次启动的时候pid号是随机分配的)。该怎么办呢?当然,可以用一些截取字符串的方法,这里介绍一下用2种方法来解决这类问题。

    一、sed+grep方法:

    首先大概了解一下sed,sed是linux里面一个非交互性的文本流编辑器(好长的定义,反正我听起来我很拗口)。解释2点:

    1,非交互性:这里非交互性是指sed工具并不直接编辑目的文本文件,而是编辑目的文件的一个缓存拷贝,只能够修改拷贝文件,不会对源文件有任何的改动!也就是说编辑并不在目的文件现场!比如我想要编辑example.log文件,如果用vi编辑器必须直接打开example.log文件,然后在里面编辑。而sed是编辑example.log文件的一个拷贝,那么你可能要问了,这个拷贝在哪儿呢?这个拷贝在缓存里面,不需要我们自己拷贝,只要你调用了sed工具来编辑,系统自动会帮我们拷贝出一个example.log文件供你去编辑,从而保护好源文件不被随意改动。

    2,文本流:文本流是指我们通过一定的shell指令对文本进行编辑,而不想vi编辑器一样需要把文件打开之后才能够进行编辑。比如我要删除example.log里面的第一行。vi里面必须先打开文件,然后选中第一行,再按下backspace键删除。如果你使用sed命令的话,就只要执行以下一行代码就可以干脆利落的删除掉第一行:sed '1d' example.log。现在可以知道,sed工具无需打开文件再进行操作,而是通过一系列命令操作文本流,所以叫做文本流编辑器。


    好,现在来解决问题:

    举个例子,比如使用ipsec的时候经常需要使用的一个命令是setkey -D来查看spi是否正常生成了。而每次ipsec连接的时候产生的spi是不一样的,当spi产生失误的时候,就会出现spi=000000000;现在我想通过一定的shell脚本获取spi的值。setkey -D产生而定输出如下图

    我们在说sed,当然使用sed来解决该问题。

    明确一下我们的目的:我们的目的是要获取上图中的一段数据:spi=152056446,并且每次如果ipsec重新启动的时候spi后面的数据会不一样(但长度一样,并且都是数字)。那么我们想到自然要用到正则表达式来匹配该段数据,然后输出到一个变量或者文件供我们后续使用。

    再来看看sed给我们提供了什么方法:sed可以很方便的把某一行打印出来,sed -n '2p' example.log会打印出第二行。也就是说sed很容易获取行,这显然不能满足我们的需求。sed不会这么简单!sed还提供了删除,追加,插入,替换等丰富的方法来对一段文本进行编辑。

    删除某一行:

    追加:把hello,i was appended here 追加到有national这一行的的后面。

    替换:sed 's/source string/destination string/' example.log


    那么,我想既然sed可以非常方便的获取到某一行数据,而它又能够对文本进行编辑,那么,我的想法是,先用sed对文本进行一定的编辑,把目标字符串编辑到某一行内,我就非常方便的获取到了


    好,照着这条思路走:

    1,编辑文本,把目标字符串放到单独的一行里面来:观察之后可以看出,该段目的字符串spi=152056446(0x0910327e)前后都有空格,那么就用空格作为重新编辑的标记位,前后换行。

    输入命令:sed 's/ /\n/g' example.log。解释下命令,s是替换的标记,第一个/ /里面有一个空格,意思是查找所有含有空格的行,最后的g表明要对该行的所有空格进行查询,而不只是查询到第一个就查询下一行,第二个/\n/是一个换行符,结合前面的空格查询语法,可以对所有的空格替换成换行符。里面的命令执行后会把文本重新编排,遇到空格就换行,这样,目标字符串就已经到了单独的一行里面去了!!!

    2,获取目标行字符串:现在就很简单了,我们可以用grep来获取(grep "spi" example.log),也可以用sed来获取(sed '/spi/p' example),把屏幕输出重定向到一个文件里面去,或者赋给一个变量,这样,我们抽取目标字符串的任务就完成了!!!

    是不是很简单!!!大笑好,下面来看awk方法

     

    二、awk方法:

    同样的,首先来大概了解一下awk方法的精髓,awk方法主要是对文本进行“列”的操作,这个对比一下sed和grep可能我们更容易理解一些,sed和grep主要是对文本进行“行”的操作,awk会把每一列都取一个名字,从第一列开始:分别为$1,$2...$n,好吧,这样就可以按照名字来分别操作列了。

    好吧,现在我们来实例操作一下。

    我们从ps输出里面去查询指定进程名字的PID,在我的终端直接输入ps x之后会显示当前进程的名字,其部分截图如下:

    现在我想获取的是当前ps x输出里面的进程名为上图中红圈部分nautilus的PID值1355,由于相同进程会在不同的时候开启的时候所获取到的PID号不一样,所以当前的PID值1355其实是个不一定的数字。于是,我们只能通过进程名字nautilus来获取当前PID。好,目的明确之后进行操作:

    1,配合使用管道,使用grep获取到包含nautilus的行:


    发现有2个nautilus,好吧,那我们就来操作2个nautilus的PID,只是需要配合使用一下sed,没事,就当复习一下;

    2,现在是awk派上用场的时候了:


    继续使用管道,可以看到,利用命令可以得到进程名为nautilus的PID列:1355和1858。

    这里先来个小插曲,简单介绍一下awk命令的语法,awk基本语法为:awk [-F] "field-operator" 'comand' inputfiles,-F和field-operator一起使用,field-operator是域分隔符,如果不使用-F选项,则默认的域分隔符为空格。后面command命令一般需要用一堆“{}”括起来,然后进行必要的操作,比较全面一点的command命令'{if($1~/^A/) print $1}',翻译一下这个命令就是,如果第一列($1)里面有匹配(~)正则表达式(/^A/)的话,那么就输出(print)到标准输出。需要注意的是,条件必须要用一堆"()"括起来,正则表达式需要用“//”括起来。当然,完全可以不要条件匹配,可以直接输出指定列,如'{print $1}'。好,awk就介绍到这里,不过awk是一个非常非常强大的文本格式化抽取的工具,需要专门的学习。后面我再写一个关于awk学习的总结。

    3,现在需要利用sed对"行"的操作了,我们获取到的第一行就是第一个nautilus的PID值,上面我们已经介绍了sed命令,所以很简单的,接着上面的管道,输入以下命令:


    很快,我们就可以得到第一个nautilus的PID值了大笑

    是不是很简单,就简单的三部操作,grep——awk——sed,这三真是文本操作里面的拼命三郎啊



    三、现在来稍微介绍一下cut方法

    cut也是一个比较强大的工具,可以对一行字符串进行多种模式匹配的剪切操作,也可以对一个排列非常整齐的文本进行操作,下面通过2个例子来大致说明 一下cut的操作。

    1,先说明cut对一行字符串的操作:

    在终端执行echo $PATH命令,可以获得当前默认的bash路径,如下图:


    其中每一个路径都被一个“:”分隔开来,现在我想获取第1个和第2个冒号之间的路径,使用cut将会非常之方便,在终端输入命令:


    确实,我们获取到了第一个冒号与第二个冒号之间的字符串“/usr/local/bin”,现在来稍微解析一下这条命令,-d和':'一起把管道输入的一行字符串进行了域的分隔,每一个分隔符(在这里是个冒号“:”)前面的字符串被称为一个域,若有n个分隔符,这个域的编号则从1开始到n+1,第1个分隔符前面的字符串为第一个域。这个域对应在该命令行则是-f后面的数字2,所以该命令`cut -d ':' -f 2`表达的意思是输出第二个分隔符“:”之前的域。

    如果我们执行

    或者是cut -d ':' -f 2-4,则可以输出第2个和第四个域的字符串,但是还多了一个分隔符,这点我也没搞懂。

    上面是是用分隔符对一行字符串进行操作,下面我们队字符串的每一个字母当成一个数组里面的元素,只是第一个元素是从1开始,而不是传统数组的0开始。这样可以进行另外一种cut操作,现在先定义一个字符串变量,并从中截取出1-5之间的字符:


    可见,这条命令很好的把字符串“hello world”从第2个字母到第5个字母cut了下来,把最后的参数进行一下修改,如下:


    则可以截取到第2个字符以及后面的所有的字符。

    2,cut对格式化整齐的文本进行操作:

    这是一段格式化比较整齐的数据,每一行前面的“declare -x”都是一模一样的,我现在想把这一段给去掉:


    其实我们发现对该文本的操作跟上的一行字符串的操作没什么区别。


    那么就验证一下对分隔符的操作是否也一样:

    发现结果确实是一样。这说明cut会把一个文本里面的每一行都独立的对待,然后再操作。


    展开全文
  • 在normal模式下按下 / 即可进入查找模式,输入要查找的字符串并按下回车。 Vim会跳转到第一个匹配。按下n查找下一个,按下N查找上一个。 格式 /字符串 二,文件未打开,在外面使用grep查找 格式 grep “要查找的...

    一、使用vim命令进入文件内查找

    在normal模式下按下 / 即可进入查找模式,输入要查找的字符串并按下回车。 Vim会跳转到第一个匹配。按下n查找下一个,按下N查找上一个。

    格式
    /字符串

    二,文件未打开,在外面使用grep查找

    格式
    grep “要查找的字符串” 文件名.

    使用参数-n可以显示查找内容在文件中的位置.

    展开全文
  • 如题,如何用shell命令来提取文档所有以a开头以z结尾的字符串呢?这些字符串长度都不一定相同。 grep只能定位到行,却不能截字符串,而用cut的话我只能想到的是截取第n位至第m位的字符串,但是如题所示,字符串并...
  • 但其实awk print $ 列是按一个字符串算的,一个字符串算作一列,就像上面的输出一样。所以$36,$40 输出的就是一些空格。 现在我想提取文件里的数字,5开头的5位,不要00,请问该如何做?PS:有很多这种log文件,...
  • 提取字符串以下字符串 error: 与 : 之间的子字符串。并消除空格。"src/network/misc/nv_net_udp.c:17: fatal error: nv_net_tools.h: No such file or directory"2.命令echo "src/network/misc/nv_...

    1. 例子

    提取字符串以下字符串 error: 与 : 之间的子字符串。并消除空格。

    "src/network/misc/nv_net_udp.c:17: fatal error: nv_net_tools.h: No such file or directory"

    2. 命令

    echo "src/network/misc/nv_net_udp.c:17: fatal error: nv_net_tools.h: No such file or directory" | sed -r 's/.*error\:(.*)\:.*/\1/' | sed s/[[:space:]]//g

    该命令涉及 sed 命令的’反向引用’章节, \1 代表 (.*)

    3. 结果

    nv_net_tools.h

    4. 拓展 : 解决编译错误

    leon$  make clean && make all 
    
    arm-hisiv100nptl-linux-gcc -c -fPIC -Wall -g -ggdb -O0 -DHI3518_CHIP -DLINUX -I./src/include -I./src/include/common -I./src/include/camera -I./src/include/conf -I./src/include/log -I./src/include/network -I./src/include/upnp -I/home/leon/nvc/arm-hisiv100nptl-linux/include src/common/nv_conf.c -o build/objs/hi3518/src/common/nv_conf.o
    /*省略中间部分*/
    arm-hisiv100nptl-linux-gcc -c -fPIC -Wall -g -ggdb -O0 -DHI3518_CHIP -DLINUX -I./src/include -I./src/include/common -I./src/include/camera -I./src/include/conf -I./src/include/log -I./src/include/network -I./src/include/upnp -I/home/leon/nvc/arm-hisiv100nptl-linux/include src/network/misc/nv_net_udp.c -o build/objs/hi3518/src/network/misc/nv_net_udp.o
    src/network/misc/nv_net_udp.c:17: fatal error: nv_net_tools.h: No such file or directory
    compilation terminated.
    make: *** [build/objs/hi3518/src/network/misc/nv_net_udp.o] Error 1

    note: 在以上编译过程中我们发现,编译器提示说找不到nv_net_tools.h文件,而现实中我们也不需要这个文件的包含了,需要删除包含nv_net_tools.h 文件中的该行代码。

    5.字符串提取 (命令行)

    目标字符串

    "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 
    

    需要提取 from , to, url , md5, level 等5个关键字后面的内容。

    //提取 from  内容
    echo "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 |  sed "s/.*from:\(.*\)/\1/" |  cut -d ',' -f1
    
    //提取 to 内容
    echo "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 |  sed "s/.*to:\(.*\)/\1/" |  cut -d ',' -f1
    
    //提取 url  内容
    echo "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 |  sed "s/.*url:\(.*\)/\1/" |  cut -d ',' -f1
    
    //提取 md5 内容
    echo "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 |  sed "s/.*md5:\(.*\)/\1/" |  cut -d ',' -f1
    
    //提取 level 内容
    echo "from":"0802070975","to":"0802071013","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"ace4b34383f964442a591559d0afb296","level":0 |  sed "s/.*level:\(.*\)/\1/" |  cut -d ',' -f1
    
    

    6.字符串提取 (脚本文件)

    ret_val="\"from\":\"0804020982\",\"to\":\"0804020998\",\"url\":\"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz\",\"md5\":\"408d261924e6c271200fdf14d3a230cc\",\"level\":0"
    
    echo ret_val is : [ $ret_val ]
    
    
    from="$(echo $ret_val | sed 's/.*from\"\:\(.*\)/\1/' |  cut -d ',' -f1 |  sed 's/"//g')"
    echo from: $from
    
    to="$(echo $ret_val | sed 's/.*to\"\:\(.*\)/\1/' |  cut -d ',' -f1 |  sed 's/"//g')"
    echo to: $to
    
    url="$(echo $ret_val | sed 's/.*url\"\:\(.*\)/\1/' |  cut -d ',' -f1 |  sed 's/"//g')"
    echo url: $url
    
    md5="$(echo $ret_val | sed 's/.*md5\"\:\(.*\)/\1/' |  cut -d ',' -f1 | sed 's/"//g')"
    echo md5: $md5
    
    level="$(echo $ret_val | sed 's/.*level\"\:\(.*\)/\1/' |  cut -d ',' -f1 | sed 's/"//g')"
    echo level: $level

    执行结果:

    ret_val is : [ "from":"0804020982","to":"0804020998","url":"http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz","md5":"408d261924e6c271200fdf14d3a230cc","level":0 ]
    from: 0804020982
    to: 0804020998
    url: http://cn.update.mynetvue.com:8060/firmware/ce7e4228521be4556f69ef2bfcb7d665.tar.gz
    md5: 408d261924e6c271200fdf14d3a230cc
    level: 0

    I.总结

    要注意命令行执行,与脚本文件执行之间的差异性。

    展开全文
  • 新需求:要求循环提取linux日志文件两个指定字符串之间的字符串。 先后尝试了grep、sed等指令,均无果而终。 直到看到下图百度搜索结果,执行以下指令终获成功:awk 'BEGIN {key=1} />>> ...

    新需求:要求循环提取linux日志文件两个指定字符串之间的字符串。

    先后尝试了grep、sed等指令,均无果而终。

    直到看到下图百度搜索结果,执行以下指令终获成功:awk 'BEGIN {key=1} />>> Script started./,/>>> Script Finished./  {print $0> "key" key ".txt"} />>> Script Finished./ {++key}' /root/Downloads/kpi.log,其中awk也是linux标准指令,key是循环次数,初始定义其值为1,>>> Script started.是指定的开始字符串,>>> Script started.是指定的结束字符串,/root/Downloads/kpi.log是日志文件。

    执行成功后,在当前路径下自动循环提取以字符串“>>> Script started.”开始到以字符串”>>> Script Finished.“结束的字符串,并分别存储到以key为前缀的小文件中

    展开全文
  • Linux中使用grep正则提取字符串 echo office365 | grep -P '\d+' -o find . -name "*.txt" | xargs grep -P 'regex' -o xargs会将find结果作为grep的输入,防止find结果过多...

    Linux中使用grep正则提取字符串

    echo office365 | grep -P '\d+' -o
    find . -name "*.txt" | xargs grep -P 'regex' -o
    

    xargs会将find结果作为grep的输入,防止find结果过多无法处理
    -P参数表明要应用正则表达式
    -o表示只输出匹配的字符串,这样我们就可以把正则匹配到的结果拿到了。

    Linux、Mac OS中使用sed正则提取字符串

    Mac OS上用正则的话要用e参数取代P参数,也可以用sed命令:
    sed命令格式:

    sed 's/oldValue/newValue/g'
    

    提取字符串

    echo here365test | sed 's/.*ere\([0-9]*\).*/\1/g'
    

    输出:

    365
    

    s表示替换,\1表示用第一个括号里面的内容替换整个字符串,sed支持*,不支持?、+,不能用\d之类,正则支持有限。

    替换字符串

    echo here365test | sed "s/365/789/g"
    
    # 注意,必须是双引号,不然引用变量会有问题!没错,就是这么严苛奇葩!
    newid=996
    echo here365test | sed "s/365/$newid/g"
    

    输出:

    here789test
    here996test
    
    展开全文
  • Linux字符串截取很常用,总结常用不同需求的几种方法假设有变量 var=http://www.aaa.com/123.htm1. # 号截取,删除左边字符,保留右边字符。echo ${var#*//}其中 var 是变量名,# 号是运算符,*// 表示从左边开始...
  • 如图,为了将txt文件每行字符串包含的数字提取出来,编写了一个程序。 思路: 找到is,然后指针后移三位,然后到达空格,则停止。再将字符转换为数字。 具体操作: 首先用fget()读取每行,然后用strstr()找到is,...
  • 1、单个字符串 grep -o str_1 filename | wc -l 备注:单个字符串可以不加引号 2、多个字符串 grep -o str_1\|str_2\|str_3…… filename | wc -l 备注:必须加引号(单、双都可以) 如果不加引号,...
  • linux中分析查看日志,有时候需要统计出文本,满足条件的行数(比如:统计访问量)下面给出了示例,非常实用的一个技巧,相信很多地方你都能使用到。一、日志,包含某...字符串的总行数 二、日志,不包含...
  • grep -r "字符串" 目录(或文件) //当前目录 grep -r "字符串" ./ -r:递归查找
  • 今天在写linux socket编程的时候,遇见一个字符串的分割提取问题,像python这样的脚本语言能直接利用现成的split() 函数直接实现,然后自己找了下,原来linux 下的C语言也可用strtok() 函数来实现: 函数原型:  ...
  • 1.在linux中字符串的截取我们可以用一个命令叫做cut,cut主要截取方法有三种 1)字节(bytes),用选项-b ,使用方法cut -b/c/f  2)字符(characters),用选项-c  3)域(fields),用选项-f 2.以字节定位 1...
  • 1.Syslog.log文件记录了一大堆数据,此时有用的数据是UserSessionSize 后面的数,利用split()函数进行字符串切分,简单高效。 2.有用的数据就在'cdz'与‘ filssd’之间 3.读取行数并切片取数  ...
  • Linux 字符串截取

    2018-03-29 16:07:29
    可以用${}分别替换得到不同的值:${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt ${file##*/}:删掉最后一个 / 及其左边的字符串:my.file.txt ${file#*.}:删掉第一个 . 及其左边的字符串...
  • [C语言]字符串处理 - 提取字符串指定部分(支持中文字符) 2008-11-5: 增加StringSubU(可处理中文字符串,以前的StringSub遇到中文会取半个字符),为此写了StrLenU和StrSetPosU函数。字符串以1开始计算,如果取的...
  • 总结下linux下shell截取字符串的fangfa
  • 今天工作接了个任务。领导给了一堆URL,让把其中的域名整理出来。 给的文档内容如下 https://new.aol.com/productsweb/?promocode=825345&ncid=txtlnkuswebr00000106 http://www.aol.com/# ...http://ww
  • 1、按照指定字符提取 ${varible##*string} 从左向右截取最后一个string后的字符串 ${varible#*string}从左向右截取第一个string后的字符串 ${varible%%string*}从右向左截取最后一个string后的字符串 ${varible%...
1 2 3 4 5 ... 20
收藏数 43,400
精华内容 17,360