Printing range of lines determined by variables with sed returns invalid command code - macos

I'm trying to print a range of lines determined by two variables set outside the script. For some reason I keep getting the invalid command code error. If I set the variables inside the script (using FT_LINE1=7 for example) it works just fine, but if the variables are set outside it doesn't work anymore.
Here is my full script:
cat /etc/passwd | grep -v "#" | sed '1d; n; d' | sed 's/:\*:.*//' | rev | sort -r |
sed -n "$FT_LINE1,${FT_LINE2}p"
The error I receive is:
sed: 1: ",p": invalid command code ,
I am using MacOS.

Related

grep <> | cat linux commands in shell script

grep "String" war_err.txt > list_of_wlan_common_war.txt | cat
This command is passing on command line. But to include in script I have to give | cat. can I know what does | cat do?
| (pipe) symbol links the output of one process to another process input. So using | cat should the print the output of prev command ran. Because cat commands take the input and print it.
However, in your case it's not doing anything. As you are redirecting the standered output of grep command to text file. So, no further piping is happening.

How to pass different values including a space separated string stored in a variable to grep command

I have a string stored in a variable like
errors="ORA-01000:|ORA-03113:|ORA-01555|ORA-19815:|shutdown|ORA-27603"
That works fine when I pass it to the grep command like
more filename.txt |grep -E $errors | awk '{print $1 $2}' >> temp.txt
But as soon as I include a string e.g "table found" in this "errors" variable like this
errors="ORA-01000:|ORA-03113:|ORA-01555|ORA-19815:|shutdown|ORA-27603|table found"
The above mentioned grep command does not work and gives the error
grep: **found**: No such file or directory
I am sort of stuck dealing with it when space separated option is passed as an "OR" option to $error
Just enclose your variable with double quotes
more filename.txt | grep -E "$errors"
If you had, say
errors="2:|a-3|table found"
the command
more filename.txt | grep -E $errors
would be like running
more filename.txt | grep -E "2:|a-3|table" found
since the shell replaces $errors with its value 2:|a-3|table found and then again splits the line into words, which would be (for the grep command only):
grep
-E
2:|a-3|table
found
therefore executing grep with the option -E, the pattern 2:|a-3|table and the file found. The content of filename.txt which is additionally piped into that command is ignored.

Deleting each line in a file from index specified in another file in bash [duplicate]

I want to delete one or more specific line numbers from a file. How would I do this using sed?
If you want to delete lines from 5 through 10 and line 12th:
sed -e '5,10d;12d' file
This will print the results to the screen. If you want to save the results to the same file:
sed -i.bak -e '5,10d;12d' file
This will store the unmodified file as file.bak, and delete the given lines.
Note: Line numbers start at 1. The first line of the file is 1, not 0.
You can delete a particular single line with its line number by
sed -i '33d' file
This will delete the line on 33 line number and save the updated file.
and awk as well
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
This is very often a symptom of an antipattern. The tool which produced the line numbers may well be replaced with one which deletes the lines right away. For example;
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(where deletelines is the utility you are imagining you need) is the same as
grep -v error logfile
Having said that, if you are in a situation where you genuinely need to perform this task, you can generate a simple sed script from the file of line numbers. Humorously (but perhaps slightly confusingly) you can do this with sed.
sed 's%$%d%' linenumbers
This accepts a file of line numbers, one per line, and produces, on standard output, the same line numbers with d appended after each. This is a valid sed script, which we can save to a file, or (on some platforms) pipe to another sed instance:
sed 's%$%d%' linenumbers | sed -f - logfile
On some platforms, sed -f does not understand the option argument - to mean standard input, so you have to redirect the script to a temporary file, and clean it up when you are done, or maybe replace the lone dash with /dev/stdin or /proc/$pid/fd/1 if your OS (or shell) has that.
As always, you can add -i before the -f option to have sed edit the target file in place, instead of producing the result on standard output. On *BSDish platforms (including OSX) you need to supply an explicit argument to -i as well; a common idiom is to supply an empty argument; -i ''.
The shortest, deleting the first line in sed
sed -i '1d' file
As Brian states here, <address><command> is used, <address> is <1> and <command> <d>.
I would like to propose a generalization with awk.
When the file is made by blocks of a fixed size
and the lines to delete are repeated for each block,
awk can work fine in such a way
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
In this example the size for the block is 2000 and I want to print the lines [1..713] and [1026..1029].
NR is the variable used by awk to store the current line number.
% gives the remainder (or modulus) of the division of two integers;
nl=((NR-1)%BLOCKSIZE)+1 Here we write in the variable nl the line number inside the current block. (see below)
|| and && are the logical operator OR and AND.
print $0 writes the full line
Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
+1 We add again 1 because we want to restore the desired order.
+-----+------+----------+------------+
| NR | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
| 1 | 1 | 0 | 1 |
| 2 | 2 | 1 | 2 |
| 3 | 0 | 2 | 3 |
| 4 | 1 | 0 | 1 |
+-----+------+----------+------------+
cat -b /etc/passwd | sed -E 's/^( )+(<line_number>)(\t)(.*)/--removed---/g;s/^( )+([0-9]+)(\t)//g'
cat -b -> print lines with numbers
s/^( )+(<line_number>)(\t)(.*)//g -> replace line number to null (remove line)
s/^( )+([0-9]+)(\t)//g #remove numbers the cat printed

Storing multiple grep parameters in a bash variable

I want to store multiple grep parameters in a bash variable, so I can define the parameters in the configuration section at the top of my file, and use it in multiple locations.
How do I need to define the variable and write the grep command?
Details
My first attempt
# CONFIG: grep parameters to further filter ...
GREP_PARAM="-E .*"
# ...
grep "^Stop " $1 | grep $GREP_PARAM | sed "..." >>$TFILE
results in
grep: ..: Is a directory
Using .\* or .\\* instead causes grep to not match anything, instead of everything.
Using grep "$GREP_PARAM" instead only works if GREP_PARAM contains a single parameter, but not otherwise; e.g. if it contains -v .*SAT.* or -v .\*SAT.\* or -v .\\*SAT.\\*, I get
grep: invalid option --
This is exactly what arrays were introduced to handle.
grep_options=(-E '.*')
grep "^Stop " "$1" | grep "${grep_options[#]}" | sed "..." >> "$TFILE"

Passing a variable to sed inside for loop

I have a for loop written in a script like so:
for((i=0;i<${#hours[#]})); do
dates=("$(last | egrep -v "reboot|wtmp|^$" | sort | tr -s " " | sed "$i q;d" | cut -f5-7 -d' ')")
done
If I simply execute the command assigned to dates in the terminal, replacing $i (inside the sed command) by a number (0,1,2...), it returns me exactly what I want, which is, for instance Nov 15 23:15.
However, when inside the for loop, I seem to have a problem with the sed command not incrementing $i. What am I doing wrong?
Your problem is that you never change i. You should probably update it in the third part of your for statement:
for((i=0;i<${#hours[#]};++i)); do
# ^^^ here

Resources