Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace more than 150000 character with sed

I want to replace this LONG string with sed
And I got the string from grep which I store it into variable var
Here is my grep command and my var variable :

var=$(grep -P -o "[^:]//.{0,}" /home/lazuardi/project/assets/static/admin/bootstrap3/css/bootstrap.css.map | grep -P -o "//.{0,})  

Here is the output from grep : string

Then I try to replace it with sed command

sed -i "s|$var||g" /home/lazuardi/project/assets/static/admin/bootstrap3/css/bootstrap.css.map

But it give me output bash: /bin/sed: Argument list too long

How can I replace it?

NB : That string has 183544 character in one line.

like image 221
Lazuardi N Putra Avatar asked Dec 10 '25 00:12

Lazuardi N Putra


2 Answers

What are you actually trying to accomplish here? sed is line-oriented, so you cannot replace a multi-line string (not even if you replace literal newlines with \n .... Well, there are ways to write a sed script which effectively replaces a sequence of lines, but it gets tortured quickly).

bash$ var=$(head -n 2 /etc/mtab)

bash$ sed "s|$var||" /etc/mtab
sed: -e expression #1, char 25: unterminated `s' command

bash$ sed "s|${var//$'\n'/\\n}||" /etc/mtab | diff -u /etc/mtab -

bash$ # (didn't replace anything, so no output)

As a workaround, what you probably want could be approached by replacing the newlines in $var with \| (or possibly just |, depending on your sed dialect) similarly to what was demonstrated above, but you'd still be bumping into the ARG_MAX limit and have a bunch of other pesky wrinkles to iron out, so let's not go there.

However, what you are attempting can be magnificently completed by sed itself, all on its own. You don't need a list of the strings; after all, sed too can handle regular expressions (and nothing in the regex you are using actually requires Perl extensions, so the -P option is by and large superfluous).

sed -i 's%\([^:]\)//.*%\1%' file

There is a minor caveat -- if there are strings which occur both with and without : in front, your original command would have replaced them all (if it had worked), whereas this one will only replace the occurrences which do not have a colon in front. That means comments at beginning of line will not be touched -- if you want them removed too, just add a line anchor as an alternative; sed -i 's%\(^\|[^:]\)//.*%\1%' file

If you want the comments in var for other reasons, the grep can be cleaned up significantly, too. (Obviously, you'd run this before performing the replacement.)

var=$(grep -P -o '[^:]\K//.*' file)

(The \K extension is one which genuinely requires -P. And of course, the common, clear, standard, readable, portable, obvious, simple way to write {0,} is *.)

like image 106
tripleee Avatar answered Dec 12 '25 16:12

tripleee


On most systems these days, the value of ARG_MAX is big enough to handle 150k without problems, but it is important to note that while the limit is called ARG_MAX and the error message indicates that the command line is too long, the real limit is the sum of the sizes of the arguments and all (exported) environment variables. Also, Linux imposes a limit of 128k (131,072 bytes) for a single argument string. Exceeding any of these limits triggers an error return of E2BIG, which is printed as "Argument list too long".

In any case, bash built-ins are exempt from the limit, so you should be able to feed the command into sed as a command file:

echo "s|$var||g" | sed -f - -i /home/lazuardi/project/assets/static/admin/bootstrap3/css/bootstrap.css.map

That may not help you much, though. Your variable is full of regex metacharacters, so it will not match the string itself. You'll need to clean it up in order to be able to use it as a regular expression. There's probably a cleaner way to do that edit, though.

like image 39
rici Avatar answered Dec 12 '25 14:12

rici



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!