-4

I want to write a bash script than prints only odd lines of file, including the first line without used sed or awk, also without &&, || and ;

Imane
  • 7
  • 2
    The requirements seem awfully arbitrary. What is the point? Is this a homework? The question (like any question) should show reasonable research effort. What is your attempt so far? Where are you stuck? – Kamil Maciorowski Mar 15 '23 at 08:02
  • 1
    Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Mar 15 '23 at 08:44
  • Voted to close as too broad - it's not clear what was attempted here, and where the problem that the asker has lie. As such, a good answer would have to explain far too much – Marcus Müller Mar 15 '23 at 09:15
  • When asking questions about text processing, please be sure to always include example input along with the desired output. Also, please show what you tried and where you faced difficulties, so that contributors trying to help don't propose solutions you already know won't work. – AdminBee Mar 28 '23 at 15:47

2 Answers2

3

With perl:

$ seq 10 | perl -ne 'print if $.%2'
1
3
5
7
9

If the input doesn't contain TAB characters, you can also do:

$ seq 10 | paste - - | cut -f1
1
3
5
7
9

With GNU grep:

$ seq 10 | grep -n '^' | LC_ALL=C grep -Po '^\d*[13579]:\K.*'
1
3
5
7
9

In any case, you shouldn't use a shell loop to process text. If that's what your teacher expects with those weird requirements, get another teacher as they'd be teaching you bad practice. A shell's role is before all to run other commands. And as a shell scripter, you want to pick the best command for the job (here perl, sed or awk) or a set of commands that collaborate together as intended by the Unix authors when they invented those pipelines some 50 years ago.

  • This perl solution is quite elegant, but it does not satisfy the requirements. From the question: "I want to write a bash script". The perl command is standalone, it's not a bash script. Your other solutions use |, so they really require a shell like bash, this makes them little closer to "bash scripts". One can wrap perl in a bash script though. It would make the answer better (the requirement would be met) and worse at the same time (objectively such wrapping is not the Right Thing). – Kamil Maciorowski Mar 15 '23 at 10:01
  • The #bash@irc.libera.chat (previously on freenode) team that is owning shellcheck, bash-hackers, bashFAQ, woodledge and so on, says that seq(1) is nonstandard, inefficient and useless Dixit greybot – Gilles Quénot Mar 15 '23 at 10:03
  • 1
    @KamilMaciorowski, that's shell code that invokes perl. Also works in the bash shell. A shell is a tool to run commands. – Stéphane Chazelas Mar 15 '23 at 10:06
  • @GillesQuénot, seq here is not part of the answer, it's a tool used to provide sample data to demonstrate the answer. – Stéphane Chazelas Mar 15 '23 at 10:07
  • So… every command is a bash script. Right? A custom binary executable that solves the OP's problem out of the box is a bash script, because one can invoke it from bash. Right? – Kamil Maciorowski Mar 15 '23 at 10:08
  • @KamilMaciorowski, yes, mytool arg is code in the shell syntax. That executes /path/to/mytool with mytool, and arg as arguments in a child process and waits for its termination. A roughly equivalent perl script would be system("mytool", "arg"); – Stéphane Chazelas Mar 15 '23 at 10:11
  • @GillesQuénot, note that the printf '%s\n' {1..n} zshism (since copied by many other shells) you used in your answer is less efficient than seq n for large values of n (where efficiency matters), as it implies storing the whole list of numbers (as strings converted from numbers likely through some sprintf() call internally) in memory several times. Compare time bash -c 'seq 10000000' > /dev/null with time bash -c 'printf "%s\n" {1..10000000}' > /dev/null for instance. – Stéphane Chazelas Mar 15 '23 at 10:17
  • Good to know, thanks – Gilles Quénot Mar 15 '23 at 10:28
  • OK, I get your point. Still, when one explicitly requests a bash script, a solution that uses bash only to invoke a tool that uses another language to do all the job single-handedly is not necessarily what he or she means. I suspect this is the reason awk and sed are explicitly forbidden. The question is probably a homework-like task and the point probably is to use bash for something more than invoking a single executable. IMO if calling the perl solution "bash script" meets the requirements, so would a solution using gawk. gawk is not forbidden, awk is; why not use gawk? – Kamil Maciorowski Mar 15 '23 at 10:43
  • 2
    @KamilMaciorowski, but IMO, giving a solution using a shell loop to process text, even one that only uses builtin commands of one particular shell implementation would be a disservice to the OP. If that's what their teacher want, they should get another teacher. – Stéphane Chazelas Mar 15 '23 at 11:06
  • And this is what earned you a +1 from me. :) – Kamil Maciorowski Mar 15 '23 at 11:10
0

You could do:

while IFS= read -r line
do 
    printf "%s\n" "$line"
    IFS= read -r _
done <"file"

Trying with seq:

while IFS= read -r line
do 
    printf "%s\n" "$line"
    IFS= read -r _
done < <(seq 10)
1
3
5
7
9
drewk
  • 241