【问题标题】:Find specify string within 2 string in bash在 bash 中的 2 个字符串中查找指定字符串
【发布时间】:2018-01-22 02:39:58
【问题描述】:

你好, 我有这样的文件:

today#123 
2934
9236
monday 

today#12341
4246
58234
monday

today#456
7768
32347
monday

但在我的文件中大约有 200k+ 行,但它是由以“today”开头并以“Monday”结尾的部分组成的

我可以轻松地将一个或所有部分分开:

awk '/today/ {show=1} show; /monday/ {show=0}' file.txt 

但我不知道如何找到带有特殊字符串的部分(在本例中为 7768) .谁能帮我 ?

1.) 每个部分的行数是随机的

2.) 文件不断变化(每天一次或两次)

结果应该是这样的:

    today#456
    7768
    32347
    monday

谢谢。

【问题讨论】:

  • '/today/ {show=1} (show ^^ $0 ~ /srchTarget/); ... ?祝你好运。
  • 它不工作 :/ 它显示语法错误,awk 不知道 ^^,我尝试只使用一个但不匹配 :( 也很抱歉打扰但你能解释一下 ^^ 应该做什么在这??对不起,也许是愚蠢的问题,但我是一个新人,找不到关于两个^^的任何信息,只有一个^
  • 参数。抱歉打错了,^^ 应该是&&

标签: regex linux bash awk


【解决方案1】:

关注awk 也可能对您有所帮助。我正在设置一个名为 value 的变量,您可以在其中提供您想要查找的任何值,并且无需更改代码中的任何内容,除了名为 value 的变量的值。

awk -v value="7768" '
/monday/ && flag{
  print;
  flag=val=""
}
/today/{
  val=$0;
  next
}
$0 ~ value{
  flag=1;
  print val RS $0;
  next
}
flag && val
'    Input_file

输出如下。

today#456
7768
32347
Monday

解释:现在也为上面的代码添加解释。

awk -v value="7768" '  ##Creating a variable named value where OP could define its variable value which OP wants to search in any line.
/monday/ && flag{      ##Searching for a string monday in any line and variable flag is NOT NULL then do following:
  print;               ##printing the current line then.
  flag=val=""          ##Nullifying the values of variable flag and val here.
}
/today/{               ##Searching for a string today here if it is found on any line then do following.
  val=$0;              ##Assigning current line value to variable val here.
  next                 ##next is out of the box keyword of awk it will skip all further statements from here.
}
$0 ~ value{            ##Checking condition here if any line value is equal to variable value then do following:
  flag=1;              ##Making variable flag value to 1 or in other words making flag value to TRUE here.
  print val RS $0;     ##Printing the value of variable val with RS(record separator, whose default value is a new line) and current line then.
  next                 ##Mentioning next will skip all further statements now.
}
flag && val            ##checking condition here if variable flag and val is NOT NULL then do following.
'  Input_file          ##mentioning Input_file name here.

【讨论】:

  • 谢谢!这非常适合我的目的!!但是,你能解释一下为什么吗?
  • 有人认为,awk 显示以“today”开头的部分,第二行与“value”一致(忽略“today”和“value”之间的所有行)然后正常继续。但就我的目的而言,这是完美的,我需要知道第一行中以“today”开头的完整字符串
【解决方案2】:

使用 awk :

awk 'show && c{
        if(show=$1==7768)print c;
        c=""
     }
     show;
     /monday/{
         show=0
     }
    /today/{
         show=1;
         c=$0
    }
    ' infile

输出:

$ awk 'show && c{if(show=$1==7768)print c;c=""}show;/monday/{show=0}/today/{show=1;c=$0}' infile
today#456
7768
32347
monday

输入:

$ cat infile
today#123 
2934
9236
monday 

today#12341
4246
58234
monday

today#456
7768
32347
monday

【讨论】:

  • 你好 Akshay,这看起来很酷,但只有当字符串在 "today" 之后的第一行时才有效。字符串可以在“今天”和“星期一”之间的任何位置,您还可以解释它为什么起作用(仅适用于第一行)?抱歉,我试图理解,但对于初学者来说并不那么容易:/
【解决方案3】:

您可以为此编写一个 bash 脚本,例如 recordfinder.sh。它可能如下所示:

# cat recordfinder.sh
#!/bin/bash
exitfn(){
echo "Usage : recordfinder.sh <filename> <searchstring>"
[ "$1" -eq 1 ] && echo "Couldn't open file" && exit 1
[ "$1" -eq 2 ] && echo "No search string provided" && exit 2
}
[ -f "$1" ] || exitfn 1
[ -z "$2" ] && exitfn 2 
awk -v str="$2" -v RS="" '$0 ~ str'  "$1"

# ./recordfinder.sh filename 7768
today#456
7768
32347
monday

希望它能给你一些灵活性:-)

【讨论】:

    【解决方案4】:
                        sed -n '/today/{:a;/monday/{/\n4246\n/p;b};N;ba}'
                             ^     ^     ^    ^          ^    ^ ^  ^  ^
                             |     |     |    |          |    | |  |  |
    dont print all lines-----+     |     |    |          |    | |  |  |
                                   |     |    |          |    | |  |  |
    if found start of block (today)+     |    |          |    | |  |  |
      then start loop with label (a)-----+    |          |    | |  |  |
      if found end of block (monday)----------+          |    | |  |  |
        then check if patterm (4246) found---------------+    | |  |  |
          if found, then print this buffer--------------------+ |  |  |
        break the loop------------------------------------------+  |  |
      load another line into buffer--------------------------------+  |
      and loop (goto label (a))---------------------------------------+
    

    测试:

    $ sed -n '/today/{:a;/monday/{/\n4246\n/p;b};N;ba}' <sample.txt 
    today#12341
    4246
    58234
    monday
    

    【讨论】:

      猜你喜欢
      • 2013-07-16
      • 2021-12-22
      • 2012-07-31
      • 1970-01-01
      • 1970-01-01
      • 2017-09-22
      • 1970-01-01
      • 2011-01-11
      相关资源
      最近更新 更多