打印两个字符串之间的文本 - 忽略第二次出现

打印两个字符串之间的文本 - 忽略第二次出现

我有一个包含很多步骤的说明文件。我想在 shell 中查看单个所需的步骤,而无需图形环境。正如指出的那样,我现在正在做什么阿莱莫尔,用于sed提取我想要查看的步骤号和下一个步骤号内的内容。

cat file | sed -n '/12/,/13/p'

第 12 步:某事
commands to execute
第 13 步:其他事

我想要让它完全按照我想要的方式做的是省略最后一行:所做的sed是从第一次出现到第二次打印,包括那些。我想避免第二个,从输出中删除最后一行并打印

第12步:一些东西
commands to execute

我如何修改我的命令来实现这一目标?我不希望有额外的命令、管道等。如果可能的话,我只想修改sed我的使用方式(或者同样简单地使用其他一些工具,例如grep),将第一个模式与第二个模式区分开来,例如“打印一个但省略另一个”。

另外,我希望命令尽可能简单,这样我就可以不费力地记住它,并在很短的时间内写出来。

答案1

Don_crissti 在评论中给了你一个解决方案(我将遵循他的文件命名约定):

sed -n '/12/,/13/{/13/!p}' UUoC.txt

这将选择文件中从第一行12到第一行的所有行,并打印它们,除非它们匹配(就是这样)。13UUoC.txt13/13/!p

另一种方法是使用head丢弃最后一行:

sed -n '/12/,/13/p' file.txt | head -n -1

答案2

don_crissti 和 terdon 完成了所有艰苦的工作;我看到这个问题,想建议使用 shell 函数来进一步减少打字/记忆,也许还可以增加一些灵活性。在输入时,我还冒昧地收紧了一些正则表达式,以避免误报。

这是外壳函数:

function step () (
  STEPS=./steps.txt
  start=$1
  stop=$((start+1))
  sed -n "/^Step $start:/,/^Step $stop:/ { /^Step $stop:/ !p }" $STEPS
)

显然,您可以随意命名它;step根据说明文件的措辞,我似乎很直观。调整STEPS变量为实际指令文件的完整路径;这样,您就不必记住或打字! -- 命令行中该文件的路径。我让该函数使用子 shell——主体周围的括号而不是大括号——因为我不想用 STEPS、start 和 stop 变量污染 shell 的命名空间。如果创建子 shell 比三个新变量更麻烦,请随意将第二组括号更改为大括号。

我对 don 和 terdon 使用的正则表达式做了两件基本的事情:

  1. 强制比赛从行首开始,并且
  2. 要求它包含单词“Step”,后跟数字,然后是冒号。

我做了这两件事,因为我可以想象指令文件中可能包含数字commands to execute,因此导致更简单的正则表达式错误匹配。

这是我使用的“魔鬼代言人”steps.txt 文件:

Step 1: one
commands to execute
Step 2: two
commands to execute
commands to execute
Step 3: three
commands to execute skip to Step 7
Step 4: four
commands to execute not step 5
commands to execute
commands to execute
commands to execute
Step 5: five
commands to execute
commands to execute
commands to execute skip to Step 6:
commands to execute
Step 6: six
commands to execute
Step 7: seven
commands to execute
Step 8: eight
commands to execute
Step 9: nine
commands to execute
Step 10: ten
commands to execute
Step 11: eleven
commands to execute
Step 12: something
commands to execute
commands to execute
Step 13: something else
commands to execute

...以及测试工具的结果(输出为step 14空):

$ for step in $(seq 1 14); do step $step; echo; done
Step 1: one
commands to execute

Step 2: two
commands to execute
commands to execute

Step 3: three
commands to execute skip to Step 7

Step 4: four
commands to execute not step 5
commands to execute
commands to execute
commands to execute

Step 5: five
commands to execute
commands to execute
commands to execute skip to Step 6:
commands to execute

Step 6: six
commands to execute

Step 7: seven
commands to execute

Step 8: eight
commands to execute

Step 9: nine
commands to execute

Step 10: ten
commands to execute

Step 11: eleven
commands to execute

Step 12: something
commands to execute
commands to execute

Step 13: something else
commands to execute

相关内容