Need help inserting text AFTER two consecutive matches using sed on macOS [closed] - macos

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
How do I insert text after two consecutive matches in a file using sed. Is this possible? If it is, how do I do the following?
My file:
abcdef()K
.xyz 1
('I want to add text here')
Note that the .xyz will be same but it can be 1 or 2 or 3 or any other number. But .xyz WILL DEFINIETLY BE under abcdef()K. I want to add text exactly AFTER the .xyz part.
Please do help guys. Thanks.

You can use this perl:
perl -0777 -pE 's/^(abcdef\(\)K\R\.xyz.*\R?)/\1(your text here)\n/mg' file
Or this awk:
awk -v ins="(your text)" '/abcdef()K/{f=1; print; next}
f && /\.xyz.*/{f=0; print; print ins; next}
{f=0; print}' file

If .xyz [0-9] is constant and is always on the line below the first match, then you can append the new line with sed
$ sed '/\.xyz [0-9]*/a New Text' input_file
abcdef()K
.xyz 1
New Text
Otherwise, you can match the first line, add a condition to substitute the match on the second line if the first matched, substitute it for itself, jump to new line and append the new text.
sed '/a.*()K/ {N;s/\.xyz [0-9]*/&\nNew Text/}' input_file
abcdef()K
.xyz 1
New Text

This might work for you (GNU sed):
sed -e '/abcdef()K/!b' -e ':a;n;/\.xyz/!ba' -e 'a new text added' file
If a line does not contain abcdef()K bail out.
Print the current line and fetch the next.
If the current line does not contain .xyz, repeat above.
Otherwise, append new text added to the current line.
sed -e '/abcdef()K/!b' -e ':a' -e 'n' -e '/\.xyz/!ba' -e 'a new text added' file
Or:
cat <<\! | sed -f - file
/abcdef()K/!b
:a
n
/\.xyz/!ba
a new text added
!

Related

Getting a line number of a specific word from a text file [duplicate]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Is grep capable of providing the line number on which the specified word appears?
Also, is possible to use grep to search for a word starting from some certain line downward?
Use grep -n to get the line number of a match.
I don't think there's a way to get grep to start on a certain line number. For that, use sed. For example, to start at line 10 and print the line number and line for matching lines, use:
sed -n '10,$ { /regex/ { =; p; } }' file
To get only the line numbers, you could use
grep -n 'regex' | sed 's/^\([0-9]\+\):.*$/\1/'
Or you could simply use sed:
sed -n '/regex/=' file
Combining the two sed commands, you get:
sed -n '10,$ { /regex/= }' file
You can call tail +[line number] [file] and pipe it to grep -n which shows the line number:
tail +[line number] [file] | grep -n /regex/
The only problem with this method is the line numbers reported by grep -n will be [line number] - 1 less than the actual line number in [file].
Or You can use
grep -n . file1 |tail -LineNumberToStartWith|grep regEx
This will take care of numbering the lines in the file
grep -n . file1
This will print the last-LineNumberToStartWith
tail -LineNumberToStartWith
And finally it will grep your desired lines(which will include line number as in orignal file)
grep regEX

How do I delete every line from a file matching the first line

I want to delete every line of a file that matches the first line, but not delete the first line.
I've tried this code so far, but it deletes all matching patterns including the first line.
sed -i "1,/$VARIABLE_CONTAINING_PATTERN/d" $MY_FILE.txt
Following your description literally - to delete every line of a file that matches the first line, but not delete the first line, awk solution:
Let's say we have the following myfile.txt:
my pattern
some text
another pattern
regex
awk sed
my pattern
text text
my pattern
our patterns
awk 'NR==1{ pat=$0; print }NR>1 && $0!~pat' myfile.txt > tmp && mv tmp myfile.txt
Final myfile.txt contents:
my pattern
some text
another pattern
regex
awk sed
text text
our patterns
Using awk. Solution depends a bit on your definition of a match:
$ cat file
1
2
3
1
12
$ awk 'NR==1{p=$0;print;next} p $0 != p' file
1
2
3
12
$ awk 'NR==1{p=$0;print;next} $0 !~ p' file
1
2
3
Therefore you should provide proper sample data with the expected output.
This might work for you (GNU sed):
sed -i '1h;1!G;/^\(.*\)\n\1$/!P;d' file
Copy the first line into the hold space (HS). For every line except the first, append the HS to the pattern space (PS). Compare the current line to the first line and print the current line if it is not the same. Delete the pattern space.

Shell Script Replace a Specified Column with sed

I have a example dataset separated by semicolon as below;
123;IZMIR;ZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC
I would like to replace values in a specified column. Lets say I want to change "ZMIR" AS "IZMIR" but only for the third column, the ones on the second column must stay the same.
Desired output is;
123;IZMIR;IZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;IZMIR;bob
BBB;ANKR;RRRR;ABC
I tried;
sed 's/;ZMIR;/;IZMIR;/' file.txt
the problem is that it changes all the values on the file not just the 3rd one.
I also tried;
awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'
and here it specifies the column but, it somehow adds spaces;
123 I;IZMIR; ZMIR 123
abc;ANKAR;aaa;999
AAA ;IZMIR; ZMIR bob
BBB;ANKR;RRRR;ABC
sed doesn't know about columns, awk does (but in awk they're called "fields"):
awk 'BEGIN{FS=OFS=";"} $3=="ZMIR"{$3="IZMIR"} 1' file
Note that since the above is doing a literal string search and replace, you don't have to worry about regexp or backreference metacharacters in the search or replacement strings, unlike in a sed solution (see https://stackoverflow.com/a/29626460/1745001).
wrt what you tried previously with awk:
awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'
That says: find "ZMIR" in the 2nd semi-colon-separated field and replace it with ";IZMIR;" and also change every existing ";" on the line to a blank character.
To learn awk, read the book Effective Awk Programming, 4th Edition, by Arnold Robbins.
If you exactly know where the word to replace is located and how many of them are in that line you could use sed with something like:
sed '3 s/ZMIR/IZMIR/2'
With the 3 in the beginning you are selecting the third line and with the 2 in the end the second occurrence. However the awk solution is a better one. But just that you know how it works in sed ;)
This might work for you (GNU sed):
sed -r 's/[^;]+/\n&\n/3;s/\nZMIR\n/IZMIR/;s/\n//g' file
Surround the required field by unique markers then replace the required string (plus markers) by the replacement string. Finally remove the unique markers.
Perl on Command Line
Input
123;IZMIR;ZMIR;123
000;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC
$. == 1 means first row it does the work only for this row So second row $. == 2
$F[0] means first column and it only does on this column So fourth column $F[3]
-a -F\; means that delimiter is ;
what you want
perl -a -F\; -pe 's/$F[0]/***/ if $. == 1' your-file
output
***;IZMIR;ZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC
for row == 2 and column == 2
perl -a -F\; -pe 's/$F[1]/***/ if $. == 2' your-file
123;IZMIR;ZMIR;123
abc;***;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC
Also without -a -F
perl -pe 's/123/***/ if $. == 1' your-file
output
***;IZMIR;ZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC
If you want to edit you can add -i option that means Edit in-place And that's it, it simply find, replace and save in the same file
perl -i -a -F\; and so on
You need to include some absolute references in the line:
^ for beginning of the line
unequivocal separation pattern
^.*ZMIR and [^;]*;ZMIR give different values where first take everything before ZMIR and sed take the longest possible
Specific
sed 's/^\([^;]*;[^;]*;\)ZMIR;/\1IZMIR;/' YourFile
generic where Old and New are batch variable (Remember, this is regex value so regex rules to apply like escaping some char)
#Old='ZMIR'
#New='IZMIR'
sed 's/^\(\([^;]*;\)\{2\}\)'${Old}';/\1'${New}';/' YourFile
In this simple case sed is an alternative, but awk is better for a complex or long line.

How to delete the first character of the line only if that line matches with the given pattern [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I need to delete first character at each line only if the given pattern matches with that line.
I have tried by replacing the first character with space, but space is appending at the each line.
sed -e '/#/s/^/ /' 2.txt > 1.txt
I need to remove the # from each line. Kindly suggest me how to make this.
You need to add a dot after ^, so that it would match the first character.
sed -e '/#/s/^./ /' 2.txt > 1.txt
Example:
$ cat file
foo
foo bar #
$ sed -e '/#/s/^./ /' file
foo
oo bar #
If you want to remove the starting # symbol then you don't need to use a search pattern,
sed 's/^#//g' file1 > file2
You can use this:
sed 's/^#//' 2.txt > 1.txt
It replaces the # at the beginning of a line by an empty string, if there is no # at the beginning of the line, then it leaves that line untouched.

sed 's/this/that/' -- ignoring g but still replace entire file

as title said, Im trying to change only the first occurrence of word.By using
sed 's/this/that/' file.txt
though i'm not using g option it replace entire file. How to fix this.?
UPDATE:
$ cat file.txt
first line
this
this
this
this
$ sed -e '1s/this/that/;t' file.txt
first line
this // ------> I want to change only this "this" to "that" :)
this
this
this
http://www.faqs.org/faqs/editor-faq/sed/
4.3. How do I change only the first occurrence of a pattern?
sed -e '1s/LHS/RHS/;t' -e '1,/LHS/s//RHS/'
Where LHS=this and RHS=that for your example.
If you know the pattern won't occur on the first line, omit the first -e and the statement following it.
sed by itself applies the edit thru out the file and combined with "g" flag the edit is applied to all the occurrences on the same line.
e.g.
$ cat file.txt
first line
this this
this
this
this
$ sed 's/this/that/' file.txt
first line
that this
that
that
that
$ sed 's/this/that/g' file.txt
first line
that that <-- Both occurrences of "this" have changed
that
that
that

Resources