0

Is there a way to grep every other line of a line? For example, just grep the odd or even lines only of a file.

I read the man page for grep and I don't see such option. I also want to get the line after the match

grep -A1 (some option here to only look at odd lines) "pattern" filename

The command I am using in my perl script:

@rows = `LANG=en_US.UTF-8 grep --include="image_args_search_*.txt" --exclude-dir=".misc" --exclude-dir=".image_args" --exclude-dir=".image_args_clean" --exclude-dir=".image_args_text" --exclude-dir=".image_args_\
init" --exclude-dir=".misc" --exclude-dir="buscar" --exclude-dir=".config" --exclude-dir="*_bak*" --exclude-dir="indexacao_de_*" --exclude-dir="*.cgi" --exclude-dir="*.pl" --exclude-dir="imagens" --exclude-dir="loaded\
_dispenses" --exclude-dir="1o_tabeliao_de_notas_de_jundiai" --exclude-dir="*_orig" --exclude-dir="checar" --exclude-dir="indexar" --no-group-separator -A1 -iHIER "$operator" $include_dirs`;

Thanks!

  • this is off-topic here and should be on [su], [unix.se] or [ubuntu.se]. Duplicate: [How to print odd line in unix](https://stackoverflow.com/q/69136974/995714) – phuclv Aug 01 '23 at 04:01
  • that said, the job of `grep` is to search for patterns so it's completely inappropriate for this task. Duplicates: [Print odd-numbered lines, print even-numbered lines](https://unix.stackexchange.com/q/26723/44425), [Show only odd lines](https://superuser.com/q/101756/241386), [How can I copy only odd numbered lines from one file to another?](https://askubuntu.com/q/998685/253474) – phuclv Aug 01 '23 at 04:03
  • 1
    You should provide an example - not sure if you just want the odd/even lines or you also want to add some filtering. Either way, you can use `sed` or `awk` instead of `grep`. – Sundeep Aug 01 '23 at 04:11
  • I want to match a pattern against the odd lines and then return also the next line like `grep -A1` – Marcos Camargo Aug 01 '23 at 04:24
  • 2
    You definitely should give sample input and output – Sundeep Aug 01 '23 at 04:33
  • If you really, really want to use `grep`, you can use a Schwartzian Transform. First augment your lines with a line number using `cat -n`, then grep for lines starting with digits ending in 0,2,4,6,8 followed by whitespace and whatever you are really looking for. – Mark Setchell Aug 01 '23 at 07:07
  • Is there a way of modifying grep? – Marcos Camargo Aug 01 '23 at 10:48

3 Answers3

2

Using awk

awk 'NR%2 && /pattern/ {print}'

edit

print line after match

 awk 'NR%2 && /pattern/ {getline; print}'
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
1

You could use a modulo operation to check whether the number is odd or even. You can use:

$ pattern="..." # replace this with your pattern
$ awk -v p="$pattern" '{if ($0~p && (NR % 2)) {print}}' file # odd rows matching pattern
$ awk -v p="$pattern" '{if ($0~p && ! (NR % 2)) {print}}' file # even rows matching pattern

then, to print the line following the match, modify the expressions to:

$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file # lines after odd rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file # lines after even rows matching pattern

this uses the solution outlined here to print the single line after each line that satisfies the conditions.


$ cat file
1
2
3
4
5

$ pattern="3"

# lines after odd rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file 
4

# lines after even rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file
$ 

$ pattern="4"

# lines after odd rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {f=1}}' file
$ 

# lines after even rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {f=1}}' file 
5

To also print the line itself that matches, with behavior like grep -A1:

$ pattern="3"

# odd lines matching pattern and line following them
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {print;f=1}}' file 
3
4

# even lines after even rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {print;f=1}}' file 
$ 

$ pattern="4"
# odd lines matching pattern and line following them
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && (NR % 2)) {print;f=1}}' file
$ 

# even lines after even rows matching pattern
$ awk -v p="$pattern" 'f{print;f=0}{if ($0~p && ! (NR % 2)) {print;f=1}}' file
4
5
Paolo
  • 21,270
  • 6
  • 38
  • 69
  • `find /home/info/public_html -name image_args_search\*txt | xargs awk -v p="António Gonçalves dos Santos" 'f{print;f=0} {if (and(NR,1) && $0~p) {f=1}}'`` awk: line 2: `function and never defined` <-- I am getting this error – Marcos Camargo Aug 01 '23 at 10:41
  • @MarcosCamargo what's the output of `awk --version` ? – Paolo Aug 01 '23 at 10:47
  • `info@linux-web-server [~]# awk -W version mawk 1.3.4 20200120 Copyright 2008-2019,2020, Thomas E. Dickey Copyright 1991-1996,2014, Michael D. Brennan random-funcs: srandom/random regex-funcs: internal compiled limits: sprintf buffer 8192 maximum-integer 2147483647` – Marcos Camargo Aug 01 '23 at 10:51
  • @Paolo : just use `NR % 2`, but more importantly, i think `$0~p` should go ahead of the `NR % 2` check, since `awk` has a very peculiar property - `regex` are cheap but `div-mods` are not. a strange way is to do `(-1)^NR < 0` in lieu of explicitly performing modulo – RARE Kpop Manifesto Aug 01 '23 at 17:58
  • @RAREKpopManifesto I wanted to offer a different solution to the one already provided... but if the OP does not have `gawk` then I will change it.. – Paolo Aug 01 '23 at 18:26
  • @MarcosCamargo do you have `gawk` on your system? – Paolo Aug 02 '23 at 11:55
  • @Paolo : even if user has `gawk`, the outcome is still the same, cuz `gawk`'s `and(x, y)` involve (background) converting to unsigned ints then performing the bitwise then re-converting to `awk-double`. it only attempts to provide a convenient wrapper for bitwise-AND (&) but the roundtrip conversions make it nearly not worth it for something like odd/even check. Ditto for `xor()` and `or()`, and user should be well aware it's a fatal exit for any negative inputs – RARE Kpop Manifesto Aug 02 '23 at 13:04
  • I don't have gawk. – Marcos Camargo Aug 02 '23 at 13:57
  • @RAREKpopManifesto fair enough, thank you for your comment. I've edited the answer – Paolo Aug 02 '23 at 14:28
  • @MarcosCamargo I've edited the answer, it works for `mawk` now too. Please check – Paolo Aug 02 '23 at 14:29
  • How about if I want to print the line that matches also like grep -A1? – Marcos Camargo Aug 02 '23 at 17:41
  • @MarcosCamargo See edit, I've added that too – Paolo Aug 03 '23 at 07:10
  • @Paolo My VM machine on GCP was stopped and I can't restart it because there are no resources. Once I can restart my VM machine, I will test it and give you credit. Thanks! – Marcos Camargo Aug 04 '23 at 19:52
0

I use sed, piping output to grep:
sed -n 'n;p' | grep [...] for even lines
sed -n 'p;n' | grep [...] for odd lines

UPDATE:
After your edit, maybe this helps:

pierpy
  • 897
  • 3
  • 14
  • 18