In the following configuration file
/etc/fine-tune.conf
We have duplicate lines as
clean_history_in_os=true
we want to delete all the lines that include clean_history_in_os=true except the first matched line in the file
what I did until now is that
sed -i '/clean_history_in_os=true/d' /etc/fine-tune.conf
but the problem is that sed delete all "clean_history_in_os=true" lines
I will happy to get ideas to solve this issue ,
You can use this
awk
to delete all matching lines except the first one:To save file in place you can use this
gnu awk
command:otherwise use temporary file as:
Here is one
sed
solution to do the same:With Perl
This increments the counter when on that line and if
> 1
it skips the line, otherwise printsThe question came up of how to pass the pattern to Perl if we have it as a shell variable. Below I assume that the shell variable
$VAR
contains the stringclean_history...
In all of this a shell variable is directly used as a pattern in a regex. If it's the literal string from the question then the code below goes as given. However, if there may be special characters they should be escaped; so you may want to precede the pattern with
\Q
when used in regex. As a general note, one should take care to not use input from the shell to run code (say under/e
).Pass it as an argument, which is then available in @ARGV
where the
BEGIN
block runs in theBEGIN
phase, before runtime (so not for the following iterations). In it shift removes the first element from@ARGV
, which in the above invocation is the value in$VAR
, first interpolated by shell. Then the filenamefile
remains in@ARGV
, so available for processing under-n
(file is opened and its lines iterated over)Use the
-s
switch, which enables command-line switches for the programThe
--
(after the one-line program under''
) marks the start of arguments for the program; then-qr
introduces a variable$qr
into the program, with a value assigned to it as above (with just-qr
the variable$qr
gets value1
, so is a flag).Any such options must come before possible filenames, and they are removed from
@ARGV
so the program can then normally process the submitted files.Export the bash variable, making it an environment variable which can then be accessed in the Perl program via
%ENV
hashBut I would rather recommend either of the first two options, over this one.
A refinement of the question given in a comment specifies that if the phrase
clean_...
starts with a#
then that line should be skipped altogether. It's simplest to separately test for thator, relying on short-circuiting
The first version is less error prone and probably cleerer.