-1

I have a file that contains 8000 lines, I want to print lines 1,4,8,12,...,7996.

I tried this code

for j in {1 .. 8000}
do
k= $((4 * $j))
print k 
sed -n $k P test.dat >> test.dat1 
done

but this error appears:

./test.csh: line 3: 4 * {1: syntax error: operand expected (error token is "{1")

what is the problem, how can I do this?

  • The error message indicates that you are using `csh`, not Bash. These are fundamentally different languages. – tripleee Dec 21 '19 at 08:24
  • If you want every 4th line starting from the first, the sequence is 1, 5, 9, 13, ... – tripleee Dec 21 '19 at 08:26
  • 1
    Avoid at all cost the usage of _csh_. It is broken, buggy and just flawed. [Top 10 reasons not to use C shell](http://www.grymoire.com/unix/CshTop10.txt) and [csh programming considered harmfull](http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/) – kvantour Dec 21 '19 at 10:15

3 Answers3

2

Use awk command:

awk 'NR%4==1{print}' input.txt

Explanation:

NR % 4 == 1 { # for every input line, which line number (NR) modulo 4 is 1
    print $0; # print the line
}
Dudi Boy
  • 4,551
  • 1
  • 15
  • 30
  • @David But that will print when the modulo is 2 or 3, too. – tripleee Dec 21 '19 at 09:07
  • Oh, correct you are -- I knew the coffee had worn off by then.... I actually think you need `awk 'NR==1 || NR%4==0'` to match `1, 4, 8, 12, 16, ...` Here is a quick test you can run `printf "%s\n" {1..20} | awk 'NR==1 || NR%4==0'` If you are not on bash, use `$(seq 1 20)` instead of the *brace-expansion*. – David C. Rankin Dec 21 '19 at 09:39
  • The reason I say that is right now you match `1, 5, 9, 13, ...` – David C. Rankin Dec 21 '19 at 09:45
  • To make this a bit smaller: `awk 'NR%4==1' file`. awk works with `pattern { action }` pairs. If a pattern is written, then the default action is `print $0`. – kvantour Dec 21 '19 at 10:12
1

If you prefer sed

sed -n '0~4p'

Interesting enough, this is the exact sample shown in man sed

'FIRST~STEP' This GNU extension matches every STEPth line starting with line FIRST. In particular, lines will be selected when there exists a non-negative N such that the current line-number equals FIRST + (N * STEP). Thus, one would use '1~2' to select the odd-numbered lines and '0~2' for even-numbered lines; to pick every third line starting with the second, '2~3' would be used; to pick every fifth line starting with the tenth, use '10~5'; and '50~0' is just an obscure way of saying '50'.

 The following commands demonstrate the step address usage:

      $ seq 10 | sed -n '0~4p'
      4
      8
dash-o
  • 13,723
  • 1
  • 10
  • 37
0

You seem to be attempting to use Bash syntax even though your question is tagged .

Even so, this has multiple errors. You can't have a space after the assignment operator, and you need to quote the sed script (otherwise it thinks P is the first file name ... Or I guess you actually mean p).

But the idea that you need to loop over the file 8000 times and print one line out of it in each iteration is also flawed. You can tell sed to print every fourth line with a single script like

sed -n -e 1p -e 5p -e 9p ... filename

I would switch to Awk for this, though.

awk 'FNR%4==1' filename
tripleee
  • 175,061
  • 34
  • 275
  • 318