Removing repeated characters with sed command - sed

How to remove repeated characters or symbols in a string
some text\n\n\n some other text\n\n more text\n
How can I make something like this using sed or another command?
some text\n some other text\n more text\n
I can remove \n like sed s/\n//g but this will remove all the characters.

You can use
sed '/^$/d' file > newfile
In GNU sed, you can use inline replacement with -i option:
sed -i '/^$/d' file
In MacOS, FreeBSD sed inline replacement can be done with
sed -i '' '/^$/d' file
sed -i.bak '/^$/d' file
See the online demo:
#!/bin/bash
s=$(echo -e "some text\n\n\n some other text\n\n more text\n")
sed '/^$/d' <<< "$s"
Output:
some text
some other text
more text

You can also use tr if it supports squeezings.
$ echo -e 'ab\n\ncd' | tr --squeeze-repeats '\n'
ab
cd

Given the following [input] or a file that is similar:
printf "some text\n\n\n some other text\n\n more text\n" | [ one of the pipes below... ]
Any of these work:
[input] | sed -n '/[^[:space:]]/p'
Or:
[input] | sed '/^$/d'
Or, if you want to filter ^[spaces or tabs]\n also:
[input] | sed '/^[[:blank:]]*$/d'
Or with awk:
[input] | awk 'NF'

Related

sed command to replace string with slashes

I need a sed command to replace a line in config file that contains /.
I want to change /var/log/haproxy to /root/myDir/haproxy in the file.
Can you please help? Thanks in advance.
If you want to replace a string containing slashes, just use a different delimiter for the sed expression:
sed 's#/var/log/haproxy#/root/myDir/haproxy#g' <file>
Here's an example:
$ echo /var/log/haproxy | sed 's#/var/log/haproxy#/root/myDir/haproxy#g'
/root/myDir/haproxy
sed will automatically use whatever character follows the s as the delimiter. These will also work:
$ echo /var/log/haproxy | sed 's#/var/log/haproxy#/root/myDir/haproxy#g'
/root/myDir/haproxy
$ echo /var/log/haproxy | sed 's^/var/log/haproxy^/root/myDir/haproxy^g'
/root/myDir/haproxy
$ echo /var/log/haproxy | sed 's%/var/log/haproxy%/root/myDir/haproxy%g'
/root/myDir/haproxy
You can also just escape the /'s in the path and keep using /, but that's harder to read, so I don't recommend it:
$ echo /var/log/haproxy | sed 's/\/var\/log\/haproxy/\/root\/myDir\/haproxy/g'
/root/myDir/haproxy

Merging 2 sed commands into 1

Is there a way to do the following in a single sed command to improve performance?
cat some_file | sed -n '/^MODIFIED/p' | sed 's/^MODIFIED\s*//g'
You could try the below sed command. -n and p helps to print those lines where the replacement takesplace. [[:space:]]* POSIX notation which matches zero or more spaces.
sed -n 's/^MODIFIED[[:space:]]*//p' some_file
OR
sed -n 's/^MODIFIED\s*//p' some_file
Example:
$ cat ri
MODIFIED foo bar
apple
mango
$ cat ri | sed -n '/^MODIFIED/p' | sed 's/^MODIFIED\s*//g'
foo bar
$ sed -n 's/^MODIFIED[[:space:]]*//p' ri
foo bar
Here is an awk version:
awk 'gsub(/^MODIFIED\s*/,"")' file
Example:
cat file
test
MODIFIED data
more MODIFIED home
awk 'gsub(/^MODIFIED\s*/,"")' file
data
You can remove both cat and sed, just use last sed like:
sed -nr 's/^MODIFIED\s*//p' some_file

sed does not recognize -r flag on AIX

thanks in advance for the help.
I have the following line that does work on linux.
myfile (extract)
active_instance_count=
aq_tm_processes=1
archive_lag_target=0
audit_file_dest=?/rdbms/audit
audit_sys_operations=FALSE
audit_trail=NONE
background_core_dump=partial
background_dump_dest=/home1/oracle/app/oracle/admin/iopecom/bdump
...
cat myfile |sed -r 's/ {1,}//g'|sed -r 's/\t*//g' |grep -v "^#"|sed -s "/^$/d" |sed =|sed 'N;s/\n/\t/'|sed -r "s/#.*//g" | sed "s/\t/;/g"|sed "s/\t/;/g"|sed -e "s,',\o042,g"
The result will be:
1;O7_DICTIONARY_ACCESSIBILITY=TRUE
2;active_instance_count=
3;aq_tm_processes=1
4;archive_lag_target=0
5;audit_file_dest=?/rdbms/audit
6;audit_sys_operations=FALSE
7;audit_trail=NONE
8;background_core_dump=partial
9;background_dump_dest=/home1/oracle/app/oracle/admin/iopecom/bdump
But, I can't figure out, how to perform the same command on AIX server.
Help is very welcome.
Regards.
Antonio.
Unless you have a compelling reason to use sed, you could use alternate tools:
awk -v OFS=';' '{print NR,$0}' filename
would produce the desired output.
You could also use perl:
perl -ne 'print "$.;$_"' filename
It appears that your sed expression would skip lines beginning with a #. As such, you could say:
perl -ne '$,=";"; !/^#/ && print ++$i,$_' filename
or something like:
grep -v '^#' filename | awk ...
reformatting your pipeline:
cat myfile |
sed -r 's/ {1,}//g' | # strip all spaces (1)
sed -r 's/\t*//g' | # strip all tabs (2)
grep -v "^#" | # delete all lines beginning `#` (3)
sed -s "/^$/d" | # delete all empty lines (4)
sed = | # interleave with line numbers (5)
sed 'N;s/\n/\t/' | # join line number and line with `\t` (6)
sed -r "s/#.*//g" | # strip all `#` comments (7)
sed "s/\t/;/g" | # replace all tabs with `;` (8)
sed "s/\t/;/g" | # do it again (9)
sed -e "s,',\o042,g" # replace all ' with " (10)
Boiling that down and using cat -n to provide the line numbers up front gets:
cat -n myfile |
sed "$(print 's/\t/;/')
$(print 's/[ \t]*//g')
s/#.*//g
/^$/d
s/'/\"/g"
which behaves identically unless I'm misreading the aix docs. The $(...) construction is command substitution, it runs that command and substitutes its output. print would be printf on linux.

Search replace regular expression variable using sed

This is probably a trivial one:
I have a file (my.file) with these lines:
>h1_c1
>h1_c2
>h1_c3
>h2_c1
>h2_c2
>h2_c3
and I want to change it in place to be:
>c1_h1
>c2_h1
>c3_h1
>c1_h2
>c2_h2
>c3_h3
I thought this ought to do it:
sed -i 's/\(\>\)\(h1\)\(\_\)\(.*\)/\1 \4 \3 \2/g' my.file
sed -i 's/\(\>\)\(h2\)\(\_\)\(.*\)/\1 \4 \3 \2/g' my.file
but it doesn't seem to work. How do I do it?
The obvious sed for your example is:
$ sed -i~ -e 's/^>\(h[0-9]\)_\(c[0-9]\)/>\2_\1/' *.foo
I tested this and it works for your example file.
Try this awk
awk -F">|_" '{print ">"$3"_"$2}' my.file > tmp && mv tmp my.file
awk -F">|_" '{print ">"$3"_"$2}' my.file
>c1_h1
>c2_h1
>c3_h1
>c1_h2
>c2_h2
>c3_h2
You can try this sed,
sed 's/>\(h[1-2]\)_\(.*\)/>\2_\1/' yourfile
(OR)
sed -r 's/>(h[1-2])_(.*)/>\2_\1/' yourfile
kent$ sed -r 's/>([^_]*)_(.*)/>\2_\1/' f
>c1_h1
>c2_h1
>c3_h1
>c1_h2
>c2_h2
>c3_h2
you add -i if you want it to happen "in-place"

How to find and replace all percent, plus, and pipe signs?

I have a document containing many percent, plus, and pipe signs. I want to replace them with a code, for use in TeX.
% becomes \textpercent.
+ becomes \textplus.
| becomes \textbar.
This is the code I am using, but it does not work:
sed -i "s/\%/\\\textpercent /g" ./file.txt
sed -i "s/|/\\\textbar /g" ./file.txt
sed -i "s/\+/\\\textplus /g" ./file.txt
How can I replace these symbols with this code?
Test script:
#!/bin/bash
cat << 'EOF' > testfile.txt
1+2+3=6
12 is 50% of 24
The pipe character '|' looks like a vertical line.
EOF
sed -i -r 's/%/\\textpercent /g;s/[+]/\\textplus /g;s/[|]/\\textbar /g' testfile.txt
cat testfile.txt
Output:
1\textplus 2\textplus 3=6
12 is 50\textpercent of 24
The pipe character '\textbar ' looks like a vertical line.
This was already suggested in a similar way by #tripleee, and I see no reason why it should not work. As you can see, my platform uses the very same version of GNU sed as yours. The only difference to #tripleee's version is that I use the extended regex mode, so I have to either escape the pipe and the plus or put it into a character class with [].
nawk '{sub(/%/,"\\textpercent");sub(/\+/,"\\textplus");sub(/\|/,"\\textpipe"); print}' file
Tested below:
> echo "% + |" | nawk '{sub(/%/,"\\textpercent");sub(/\+/,"\\textplus");sub(/\|/,"\\textpipe"); print}'
\textpercent \textplus \textpipe
Use single quotes:
$ cat in.txt
foo % bar
foo + bar
foo | bar
$ sed -e 's/%/\\textpercent /g' -e 's/\+/\\textplus /g' -e 's/|/\\textbar /g' < in.txt
foo \textpercent bar
foo \textplus bar
foo \textbar bar