zoukankan      html  css  js  c++  java
  • 刷题中熟悉Shell命令之Tenth Line和Transpose File [leetcode]

    首先介绍题目中要用的4个Shell命令 sed awk head tail的常用方法。(打好地基,才能建成高楼!)

    sed:(转自:http://www.cnblogs.com/barrychiao/archive/2012/09/27/2706300.html)

    1.定位行

    sed命令用来处理文本,在处理前首先要找得到待处理的行,这是逻辑上必须的。所以需要首先定位,然后对定位到的各行进行各种处理,包括插入,删除,替换等。
    sed -n '10p' testfile // sed命令默认会打印出经过处理后所有的文本,-n选项则不打印这种默认文本。10为要定位的行,找到之后执行p命令,打印这一行。
    sed -n '1,10p' testfile // 打印1-10行。
    sed -n '2,$p' testfile // 打印第二行到最后一行。
    sed -n '3~2p' testfile // 打印第3,5,7,9,…….行,你懂得。
    sed -n '/Barry/,10p' testfile // 首先找到第一个匹配/Barry/(可以是其他基本正则表达式)的行,打印从这一行到第10行。
    sed -n '1,3!p' testfile // 打印1-3行以外的行("!"的作用)。
    sed -n '1{n;p}' testfile // 首先定位到第一行,然后执行命令n,定位到第一行的下一行,然后执行p打印,可见定位之后可以用 {}执行命令组合。
    sed -n 'p' testfile // 什么都不写,则定位全部的行。
    采用a,b这种模式定位时,首先定位a(如果超出范围或者未找到,就不会去查找b),然后定位b,如果b这一行在a的上面会出现什么状况呢?例如:
    sed -n '/Barry/,/Hello/p' testfile 
    该首先会定位到/Barry/,如果/Hello/这一行在/Barry/这一行上面,则只打印/Barry/这一行。为什么会这样?原来,sed定位是不回退的,即找到了/Barry/这一行之后,就从这一行下面找/Hello/,当然找不到了,所以只打印了/Barry/这一行。

    2.命令

    在定位之后当然是执行指定的命令了:d命令是删除命令。a命令在行后插入一行。i命令在行前插入一行。c命令替换行,当替换目标是连续的行时,把整体替换成一行。-r 选项使sed支持扩展正则表达式。s命令是替换命令,通常格式是line1,line2s/字符串1/字符串2/g,即把line1~line2的字符串1全部用字符串2代替,字符串1可以是正则表达式。这里不再对正则表达式详细介绍。如果末尾不加g字符,则表示只替换每行的第一个匹配的字符串。$是正则表达式的行尾标志。y命令替换以字符为单位,而s命令以字符串为单位。

    看实例:
    sed '1,3d' testfile // 删除1-3行,打印剩余的文本,注意,此时文件本身并没有改变。
    sed -n '5,10a helloworld' testfile // 在5-10行每一行后面都增加一行 helloworld。
    sed -n '5,10i helloworld' testfile // 在5-10行每一行前面都增加一行 helloworld。
    sed -n ‘5~3c helloworld’ testfile //把5,8,11,14,17,20,23,26……依次替换为helloworld。
    sed -n '5,10c helloworld' testfile //  把5-10行整体替换成一行helloworld。
    sed -n -r '5,10s/yes|Yes/no/gp' testfile // 5-10行的yes或者Yes被替换成no。 

    sed '1,10s/$/helloworld/' testfile // 在1~10行中,替换每行的行尾设置为helloworld。
    sed '5,10y/abc/ABC/' testfile // 5-10行的a被换成A,b被换成B,c被换成C,类似tr命令的功能。
    sed '/My/r textfile' testfile // r命令是读命令,sed使用该命令将一个文本文件中的内容加到当前行的下面。
    sed -n '1,10w newfile' testfile // 将1-10行写入newfile。w命令可以将指定的行写入指定的文件。
    sed -n '/root/{=;p}' testfile // 定位到/root/行之后,打印行号,然后打印这一行。"="是打印行号的命令。

     3.特殊选项 

    -i选项表示对真实文件进行操作,所做的更改将保存到文件中。-s,则将多个文件读入,当作一个整体处理,-s选项使分别处理。e选项可以进行多次处理。每次匹配到的行执行多个命令。命令之间用";"分隔。

    sed -i '1,10d' testfile // 直接在文件中删除1~10行。
    sed -s '1d' testfile1 testfile2 testfile3 // 此处有三个文件,如果不加-s,则将三个文件读入,当作一个整体处理,-s选项使分别处理。
    sed -e '/root/p' -e '/Barry/d' testfile // 此处用-e选项可以进行多次处理,第一次打印/root/行,第二次删除/Barry/行。
    sed -e '/root/{n;p}' -e '/Barry/{n;d}' testfile // 每次处理时,可以对每次匹配到的行执行多个命令。命令之间用";"分隔。

    awk

    命令行格式:

    awk [-F  field-separator]  'commands'  input-file(s)
    其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
    在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
    用$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推

    'commands'的格式
    awk '{pattern + action}' {filenames}   '{pattern + action}'可以被总结为模式和操作

    模式pattern :
      转自: http://man.linuxde.net/awk
    • /正则表达式/:使用通配符的扩展集。
    • 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
    • 模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
    • BEGIN语句块、pattern语句块、END语句块。

      操作action:

        操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内{}。

        主要部分是:

    • 变量或数组赋值
    • 输出命令
    • 内置函数
    • 控制流语句

      awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

      一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中,

      例如: awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename

      awk "BEGIN{ i=0 } { i++ } END{ print i }" filename


      第一步:执行BEGIN{ commands }语句块中的语句;

      第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

      第三步:当读至输入流末尾时,执行END{ commands }语句块。

      BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

      END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

      pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    awk的内置变量
    ARGC               命令行参数个数
    ARGV               命令行参数排列
    ENVIRON            支持队列中系统环境变量的使用
    FILENAME           awk浏览的文件名
    FNR                浏览文件的记录数
    FS                 设置输入域分隔符,等价于命令行 -F选项
    NF                 浏览记录的域的个数
    NR                 已读的记录数
    OFS                输出域分隔符
    ORS                输出记录分隔符
    RS                 控制记录分隔符

      关于AWk命令的具体使用详解,请参考http://man.linuxde.net/awk。

    Head 和 Tail(+从文章开头数,-从文章尾部数)

    head命令是用来查看具体文件的前面几行的内容

    tail命令是用来查看具体文件后面几行的内容

      -q 隐藏文件名

      -v 显示文件名

      -c<字节> 显示字节数

      -n<行数> 显示的行数

    head -n 5 log2014.log  //文章前5行

    head -n -2 log2014.log //将倒数第二行之前的内容都输出

    tail [+ / - num ] [参数 ] 文件

    tail -n +4 log2014.log //文章第四行之后的内容都输出(包含第四行)

    tail -n -2 log2014.log //文章倒数两行的内容都输出

    题目描述:

    How would you print just the 10th line of a file?

    For example, assume that file.txt has the following content:

    Line 1
    Line 2
    Line 3
    Line 4
    Line 5
    Line 6
    Line 7
    Line 8
    Line 9
    Line 10
    

      

    Your script should output the tenth line, which is:

    Line 10

    Hint:

    1. If the file contains less than 10 lines, what should you output?

    2. There's at least three different solutions. Try to explore all possibilities.

    题目大意:

    输出一个文件的第10行。

    思考:

    1. 如果文件包含内容不足10行,应该输出什么?

    2. 有至少3种不同的解决方法,尝试列举所有的可能方案

    BASH脚本

    解法一:使用awk

    1 # Read from the file file.txt and output the tenth line to stdout.
    2 awk 'NR == 10' file.txt #NR代表已读过的记录数

    解法二:使用sed

    1 # Read from the file file.txt and output the tenth line to stdout.
    2 sed -n '10p' file.txt

    解法三: 使用head和tail

    1 # Read from the file file.txt and output the tenth line to stdout.
    2 head -n +10 file.txt | tail -n -1   #这种对于文件内不足10行的,就会出现错误,文件有9行 则输出9 ,为8行则输出8
    1 # Read from the file file.txt and output the tenth line to stdout.
    2 tail -n +10 file.txt | head -n +1

     Transpose File(类似于矩阵转置问题)

     1 awk '{
     2     for(i=1;i<=NF;i++){
     3         if(NR==1){
     4             s[i]=$i;
     5         }else{
     6             s[i]=s[i]" "$i;
     7         }
     8     }
     9 }END{
    10     for(i=1;i<=NF;i++)
    11         print s[i];
    12 }' file.txt
    幸运之神的降临,往往只是因为你多看了一眼,多想了一下,多走了一步。
  • 相关阅读:
    Socket网络通信之数据传递
    多线程中join()的用法
    JAVA多线程实现的三种方式
    通过读取配置文件,启动mongodb
    利用ajax获取网页表单数据,并存储到数据库之二(使用SSH)
    利用ajax获取网页表单数据,并存储到数据库之一(使用JDBC)
    Null reference pointer was passed to the stub when not debugging with IE
    代码生成了解
    Linq to sql 入门
    SharePoint 2013 入门
  • 原文地址:https://www.cnblogs.com/strongYaYa/p/5684200.html
Copyright © 2011-2022 走看看