Linux CentOS sed command with regex issues - regex

I have a txt file under CentOS in which I want to replace any "\t\n" with "\t\t". I tried this:
sed -i -E 's/\t\n/\t\t/g' myfile.txt
but it doesn't work. I don't know if CentOS doesn't support regex in sed.
Any help is appreciated!
p.s.
Input(two lines):
1\t2\t3\t$
4\t5\t6\t$
Output(one line):
1\t2\t\3\t\t4\t5\t6\t\t
In Editplus, the find regex is '\t\n' and the replace is '\t\t'. Then all lines ending with '\t\n' will become one line, and each '\n' is replaced by one additional '\t'.
p.s.
my file is read like this (cat -A myfile.txt)

You may use this perl command to join lines if previous line has a single tab:
perl -i -0777 -pe 's/(\S\t)\n(?!\z)/$1\t/g' excel.log
(?!\z) is a negative lookahead to fail this match for last line of the file.

You need to escape the backslashes.
sed -i -E 's/\\t\\n/\\t\\t/g' myfile.txt

Related

General solutions to replace string regex preceded and followed by '\n'

I have a file in CentOS which looks like following
[root#localhost nn]# cat -A excel.log
real1$
0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real2$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real3$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real4$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real5$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real6$
I would like to replace \nreal[2-6]\n with \t\t\t' and have tried unsuccessfully the following
sed -i 's/\nreal[2-6]\n/\t\t\t/g' file
It seems that sed has difficulty to deal with line break. Any idea to fulfill the regex in CentOS?
Much appreciated!
If you want to consider perl then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])(?:\n|\z)/\t\t\t/g' file
If you want to avoid last real\d+ line to be replaced with \t\t\t then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])\n(?!\z)/\t\t\t/g' file
(?!\z) is negative lookahead to fail the match when we have line end just ahead of us.
With GNU sed, you need to use the -z option:
sed -i -z 's/\nreal[2-6]\n/\t\t\t/g' file
# ^^
Now, that you also want to handle specific alternations, you need to enable the POSIX ERE syntax, either with -r or -E option:
sed -i -Ez 's/\n(51[23]real|real[2-6])\n/\t\t\t/g' file

sed remove lines that starts with a specific pattern

I'm trying to use sed command with a regex pattern that works fine with grep. But it's not matching nothing with sed command.
I have a text file and want to delete each line that starts with (wow or waw).
This is the command I'm using But it's not working.
sed -i '/^w\(o\|a\)w/d' text.txt
I tried using the same pattern with grep and it works fine:
grep '^w\(o\|a\)w' text.txt
Anything wrong with the regex in the sed command ?
With GNU sed, you can use
sed -i '/^w[oa]w/d' file
With FreeBSD sed, use
sed -i '' '/^w[oa]w/d' file
Here, [oa] is a bracket expression matching either o or a.
See an online sed demo:
sed '/^w[oa]w/d' <<< "wow 1
waw 2
wiw 3"
Output: wiw 3.

Regex for grep from end of line

for a line in /etc/passwd
I want to grep from end of line ($) to the first ":" from the end of the line.
For example,\n
johndoe:x:39:39:John Doe:/var/lib/canna:/sbin/nologin
I want to grep "/sbin/nologin"
What is the right regex to use for my grep command?
If you don't mind the colon being selected too, then use:
grep -o -e ':[^:]*$' /etc/passwd
That selects a colon not followed by any other colon and then end of line and only print what matches.
If you don't want the colon and you do have a PCRE-enabled grep, look at Regex lookahead for 'not followed by' in grep?; you'll need to adapt it to do look-behind instead of look-ahead, that's all.
If you don't have grep with -o, use sed instead (omitting the colon):
sed -n -e '/.*:\([^:]*\)$/ s//\1/p' /etc/passwd
This is probably the most portable solution.
(On macOS Sierra, and Mac OS X, the /etc/passwd file has comment lines at the top starting with a #. The sed command does not print those lines because they don't have any colons on them. This works cleanly on Macs as well as Linux and other variants of Unix, therefore. It uses no advanced (aka non-portable) features of sed.)
How about use cut, This is more straight for this:
echo 'johndoe:x:39:39:John Doe:/var/lib/canna:/sbin/nologin' | cut -d ':' -f 7

sed regex search not giving proper results

My file have text in multiple lines in following format
number:characters
example
123:dfgd
3:hjdfg
23423:fdlgj
I want to extract all lines where number part has only one digit using following sed
sed '/^\d:/p' file.txt
But this is printing all the lines. Please point out the issue in the command.
You are pretty close. You can use this sed command:
sed -n '/^[0-9]:/p' file
3:hjdfg
-n is to suppress regular output
[0-9] is to match a digit (\d isn't supported by sed regex even in extended regex mode)

Replacing a fixed-position character field using Perl or sed

I need to replace a particular range of characters in each line of a file.
I tried this
perl -i -pe 'r77,79c/XXX/g' file
I am trying to change the 77th to 79th characters to XXX using Perl, but above code is not working.
you want to replace chars at position [77-79] with XXX?
try
perl -i -piorig_* -e "substr($_,76,3)=XXX" file
a backup file called orig_file will be created cause of preventing possible dataloss..
perl -i -pe 's/.{76}\K.../XXX/' file
You wrote:
Actually i want to search a pattern in a file and whatever lines matching that pattern needs to be replaced to 50th & 51st character to XX
Using sed:
sed -r '/pattern/s/^(.{49})..(.*)$/\1XX\2/' file
sed "/pattern/ s/^\(.\{49\}\)../\1XX/" YourFile
we don't touch the end