SED syntax to insert a string between two line numbers? - sed

For example, in a text file /location/file.txt:
some random text
some more random text
some more random text
I would like to insert a string of words in between the second line.

Two insert between 2 and 3 (after 2):
sed '2{a\
two words
}' input
To insert between 1 and 2 (before 2):
sed '2{i\
two words
}' input
Or if you don't want newlines:
sed '2a\\ttwo words' input

With awk:
awk '{print} NR==2{print "here is some extra text after line 2"}' file
If you want to overwrite the original file:
awk '{print} NR==2{print "here is some extra text after line 2"}' file > tmp && mv tmp file

This will add one line "new line here" between the second and third line.
awk 'NR==3{print "new line here"}1' your_file
if you want to do it inplace use
perl:
perl -pi -e 'print "new line here.\n" if($.==3)' your_file

Related

sed to operate on a range of lines plus a single line

Let's say I have a file file.txt:
hello
world
hi
there
this
wow
I know sed can operate on one line like:
sed -n '2p' file.txt
or a range :
sed -n '2,4p' file.txt
but how to operate on one specific line plus a range ?
sed -n '1line and 4,5' file.txt or in words print the first line and the range from 4th to 5th line ??
Could you please try following. Written and tested with shown samples in GNU sed. This will print line which has string hello and will print lines from 2nd line to 4th line.
sed -n '/hello/p;2,4p' Input_file
OR to give single line number along with a lines range try following:
sed -n '1p;2,4p' Input_file
Explanation: Using -n option to stop printing for all lines first. Then checking condition if line contains /hello then printing that line by p option. After that giving 2nd statement separated by ; to print a range from 2nd line to 4th line number.

sed: How do I delete the first 100 lines of a text file

I would like to delete the first 100 lines of a text file using sed. I know how delete to the first line by using:
sed '1d' filename
or the 100th line by typing
sed '100d' filename
How do I specify a range? I thought something like this would work:
sed '1:100d' filename
However, this obviously didn't work. Can someone show me how to specify a range? Thanks in advance for your help.
This should work in gnu sed
sed '1,100d' file
awk can also be used to print data based on conditions related to rows.
Like: Following will print the lines (Records in terms of awk) whose number is greater than 100.
awk 'NR>100' inputfile
One can also use other conditions like:
awk 'NR==100' inpuftile #this will print the 100th line
awk 'NR<100' inputfile #this will print 1-99th line
awk 'NR>100' inputfile #this will print from 101st line onwards
awk 'NR>=100' inputfile #this will print from 100th onwards
try: following too:
sed -n '1,100p' Input_file

Adding characters to the end of a line using SED

I am trying to add there exclamation points to the end of each line in this text file. I was told I need to switch all characters from lower case to upper case and have done so with string below. I am not sure how to incorporate the exclamation points in the same sed statement.
cat "trump.txt" | sed 's/./\U&/g'
Consider this sample text:
$ cat ip.txt
this is a sample text
Another line
3 apples
With sed command given in question which uppercases one character at a time with g flag
$ sed 's/./\U&/g' ip.txt
THIS IS A SAMPLE TEXT
ANOTHER LINE
3 APPLES
To add some other characters at end
$ sed 's/.*/\U&!!!/' ip.txt
THIS IS A SAMPLE TEXT!!!
ANOTHER LINE!!!
3 APPLES!!!
.* will match entire line and & will contain entire line while replacing
g flag is not needed as substitution is happening only once
Here is awk version , where all the text will be converted into uppercase and then three exclamations would be added.
awk '{$0=toupper($0) "!!!"}1' input
THIS IS A SAMPLE TEXT!!!
ANOTHER LINE!!!
3 APPLES!!!
Explanation:
$0 is entire line or record. toupper is an awk inbuilt function to convert input to uppercase. Here $0 is provided as input to toupper function. So, it will convert $0 to uppercase.finally uppercased $0 and !!! would be substituted to $0 as new values.
Breakdown of the command:
awk '{$0=toupper($0)}1' input # to make text uppercase.
awk '{$0= $0 "!!!"}1' input # to add "`!!!`" in the end of text.
Or bash way: ^^ sign after variable name will make contents of variable uppercase.
while read line;
do
echo "${line^^}"'!!!' ;
done <input

linux + cut file until specific word

I have the file with the following format
How to cut the file until the line that start with number 2 ( not include line 2 )
before the new line with number 2 could be spaces or TABs ,
remark - implementation can be done with ksh or awk or sed or perl one liner etc
file:
* 0
Any text
Any text
.
.
1
Any text
Any text
.
.
2
Any text
Any text
.
.
3
Any text
Any text
.
.
Just exit when you encounter the line you want to stop at:
awk '/[[:space:]]*2/{exit}1' file
Update: [[:space:]] will take care of spaces, tabs etc.
Use sed to delete everything after (and including) the matching line
$ sed '/^[ ]*2/,$d' input.txt
That's a space and a tab in the character class.
You can "play" with a flag, that deactivates when the line is found:
awk 'BEGIN{f=1} /^2/{f=0} f' file
BEGIN{f=1} initializes the flag as true. /^2/{f=0} unsets it when a line starts with 2, f, when true, prints the line.
To also check lines having 2 after some spaces, you can do:
awk 'BEGIN{f=1} /\s*2/{f=0} f' file
Perl one-liner:
perl -pwe 'exit if $_ =~ /^\s*2/' file
This allows for any number of spaces between the start of the line and the number 2
Use the instruction Q with sed so that it doesn't parse the rest of the file once it has found the appropriate end line:
sed '/^\s*2/Q' file

sed: replace pattern only if followed by empty line

I need to replace a pattern in a file, only if it is followed by an empty line. Suppose I have following file:
test
test
test
...
the following command would replace all occurrences of test with xxx
cat file | sed 's/test/xxx/g'
but I need to only replace test if next line is empty. I have tried matching a hex code, but that doesn ot work:
cat file | sed 's/test\x0a/xxx/g'
The desired output should look like this:
test
xxx
xxx
...
Suggested solutions for sed, perl and awk:
sed
sed -rn '1h;1!H;${g;s/test([^\n]*\n\n)/xxx\1/g;p;}' file
I got the idea from sed multiline search and replace. Basically slurp the entire file into sed's hold space and do global replacement on the whole chunk at once.
perl
$ perl -00 -pe 's/test(?=[^\n]*\n\n)$/xxx/m' file
-00 triggers paragraph mode which makes perl read chunks separated by one or several empty lines (just what OP is looking for). Positive look ahead (?=) to anchor substitution to the last line of the chunk.
Caveat: -00 will squash multiple empty lines into single empty lines.
awk
$ awk 'NR==1 {l=$0; next}
/^$/ {gsub(/test/,"xxx", l)}
{print l; l=$0}
END {print l}' file
Basically store previous line in l, substitute pattern in l if current line is empty. Print l. Finally print the very last line.
Output in all three cases
test
xxx
xxx
...
This might work for you (GNU sed):
sed -r '$!N;s/test(\n\s*)$/xxx\1/;P;D' file
Keep a window of 2 lines throughout the length of the file and if the second line is empty and the first line contains the pattern then make a substitution.
Using sed
sed -r ':a;$!{N;ba};s/test([^\n]*\n(\n|$))/xxx\1/g'
explanation
:a # set label a
$ !{ # if not end of file
N # Add a newline to the pattern space, then append the next line of input to the pattern space
b a # Unconditionally branch to label. The label may be omitted, in which case the next cycle is started.
}
# simply, above command :a;$!{N;ba} is used to read the whole file into pattern.
s/test([^\n]*\n(\n|$))/xxx\1/g # replace the key word if next line is empty (\n\n) or end of line ($)