2

I have an instruction file with a lot of steps. I'd want to view a single desired step in a shell, without graphical environment. What I do right now, as pointed out by alemol, is using sed to extract what's inside the number of the step I'd like to view and the next one.

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

Step 12: something
commands to execute
Step 13: something else

What I miss to make it do exactly what I want is omitting the last line: what sed do is print from first occurrence to second, including those. I'd want to avoid the second, removing last line from output and printing just

Step 12: something
commands to execute

How do I modify my command to achieve that? I'd prefer no additional commands, pipelines and such. If it's possible, I'd just want to modify the sed use I make (or an equally straightforward single use of some other tool like grep), differentiating the first pattern from the second, such as "print one but omit the other".

Also, I'd want the command to be as easy as possible, so that I can memorize it without huge effort, and write it in little time.

  • @don_crissti Thanks, it is more than perfect. You can write that as an answer, I will definitely accept it. – Jeffrey Lebowski Jun 2 '16 at 14:08
  • Jeff, you're welcome - this has been asked before, I just don't have the time to search for it right now. – don_crissti Jun 2 '16 at 14:09
  • If any of the existing answers solves your problem, please consider accepting it via the checkmark. Thank you! – Jeff Schaller Apr 23 '17 at 12:55
1

Don_crissti gave you one solution in the comments (and I will follow his file naming convention):

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

That will select all lines from the first 12 to the first 13 in the file UUoC.txt, and print them unless they match 13 (that's what /13/!p does).

Another approach would be to use head to discard the last line:

sed -n '/12/,/13/p' file.txt | head -n -1
| improve this answer | |
  • or sed '$d' to discard last line – Sundeep Jun 3 '16 at 4:46
1

don_crissti and terdon did all the hard work; I saw this question and wanted to suggest using a shell function to further reduce typing / memorization, and perhaps add some flexibility. While typing it up, I've also taken the liberty of tightening down the regular expression some, to avoid false positives.

Here's the shell function:

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

You're obviously free to name it whatever you like; step seemed intuitive to me based on the wording of the instruction file. Adjust the STEPS variable to be the full path to the actual instruction file; that way, you don't have to remember -- or type! -- the path to that file at the command-line. I made the function use a subshell -- parens around the body instead of braces -- because I didn't want to pollute your shell's namespace with the STEPS, start, and stop variables. If creating a subshell is more bothersome than three new variables, feel free to change the second set of parenthesis over to curly braces.

I did two basic things to the regular expression that don & terdon used:

  1. Forced the match to start at the beginning of the line, and
  2. required it to contain the word "Step" followed by the number, followed by a colon.

I did both of those things because I can imagine the instruction file potentially containing numbers inside the commands to execute and so causing the simpler regex to falsely match.

Here's the "devil's advocate" steps.txt file I was using:

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

... and the results of a test harness (the output from step 14 is empty):

$ 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
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.