如何编辑 2 个符号之间的文本范围?awk、sed、正则表达式

Tux*_*ife 6 bash regex sed awk

使用“*”符号,(不必是那个,任何特殊字符都可以表示),我如何编辑文本:

*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*
Run Code Online (Sandbox Code Playgroud)

对此:

strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Run Code Online (Sandbox Code Playgroud)

第一个匹配星号之后的每个字符都将放置在每一行上,直到找到第二个星号匹配项。

关于我如何解决这个问题的任何线索?(最好使用 sed 或 awk,但如果您能想到其他方法,请将您的代码发给我!)

我知道如何删除所有包含星号的行,这只是我想不到的字符放置部分

mur*_*uru 12

这段awk代码就足够了:

awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'
Run Code Online (Sandbox Code Playgroud)

分解:

  • 使用*作为字段分隔符。这样,我们可以简单地检查字段数 ( NF) 以确定是否到达块的开头或结尾。
  • 当有两个字段时,我们保存第二个字段label并继续下一行。
  • 从那时起,我们将其附加label到当前行,然后打印。如果标签为空,我们就在一个块之外,没有任何影响。如果没有,我们会得到所需的输出。


ste*_*ver 8

在 中sed,您可以在删除“特殊”行之前将其复制到保留空间中

sed -e '/^\*/{h;d;}'
Run Code Online (Sandbox Code Playgroud)

然后将保留空间附加到每个后续的模式空间,替换生成的换行符和标记字符

    -e '{G;s/\n\*//;}'
Run Code Online (Sandbox Code Playgroud)

用你的数据测试它,

$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Run Code Online (Sandbox Code Playgroud)

注意:这不会在遇到第二个星号时停止;它的作用完全相同,但它附加*后什么都没有 - 直到它匹配下一个*sometext.


ter*_*don 7

这是一种 Perl 方式:

$ perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Run Code Online (Sandbox Code Playgroud)

解释

-n将导致 Perl 读取输入文件的每一行,将其保存在特殊变量中$_,这-l将导致它 i \n) 从每一行中去除尾随的换行符 ( ) 和 ii) 向print. 的-e是施加于每行的脚本。

  • /^\*(.*)/: 匹配以星号开头的行并将星号后的所有内容另存为$1(这就是括号的作用)。

  • || print "$_$1"':||是合乎逻辑的OR。因此,print只有当当前行不以星号开头时才会执行。如果是这样,我们打印当前行 ( $_) 以及当前保存的任何内容$1(星号后面的模式)。


像往常一样,有很多方法可以做到这一点。一个愚蠢且低效但突出了 shell 的字符串操作功能的方法是:

$ while read line; do 
    [[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat"; 
  done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable
Run Code Online (Sandbox Code Playgroud)

解释

  • while read line; do ... ; done < file:这是一个经典的while循环,它将读取输入文件的每一行file并将其保存为$line.
  • [[ $line =~ ^\* ]] && pat="${line#\*}": 如果该行以 an 开头*,则删除之后的所有内容(这就是它的${line#\*}作用,有关更多详细信息,请参见此处)并将其另存为$pat. * || printf "%s%s\n" "$line" "$pat";:如果前一个命令失败(因此,该行不以星号开头),则打印该行和 的当前值$pat