Reputation: 933
I have a list similar to :
What do you want to do?
Import a text file by opening it in Excel
Import a text file by connecting to it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
using SED I can find a match on 'connecting' and replace the line:
sed 's^.*connecting.*^Import a text file by opening it^g' crontab
This should change the above list to :
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
However what I need to be able to do is:
if a line exists containing the word connecting
, then replace that line,
if the line doesn't exist add it to the end of the list as a new line.
I know I can do echo "Import a text file by opening it" >> list
which would add the line to the end of the list, but is there anyway I can do this within one command ? or commands that can be run in one instance ?
Thanks
Upvotes: 0
Views: 430
Reputation: 44063
An easy way is to use awk
:
awk 'BEGIN { s = "Import a text file by opening it" } /connecting/ { $0 = s; n = 1 } 1; END { if(!n) print s }' filename
That works as follows:
BEGIN { # Before anything else:
s = "Import a text file by opening it" # Remember the string by a shorter
# name so we don't have to repeat it
}
/connecting/ { # If a line contains "connecting",
$0 = s # replace the line with that string
n = 1 # and raise a flag that we've done so.
}
1 # print
END { # in the end:
if(!n) { # If the string wasn't yet printed,
print s # do it now.
}
}
Alternatively, you can use sed
's hold buffer. For example:
sed '1 { x; s/.*/Import a text file by opening it/; x; }; /connecting/ { s/.*//; x; }; $ { G; s/\n$//; }' filename
This works as follows:
1 { # while processing the first line
x # swap hold buffer, pattern space
s/.*/Import a text file by opening it/ # write text to pattern space
x # swap back.
} # Now the hold buffer contains the
# line we want to insert, and the
# pattern space the first line.
/connecting/ { # For all lines: If a line contains
# "connecting"
s/.*// # empty the pattern space
x # swap in hold buffer.
# If this happened, the hold buffer
# will be empty and the pattern space
# will contain "Import a ..."
}
$ { # Last line:
G # Append hold buffer to pattern space.
# If the hold buffer is empty (i.e.,
# was used somewhere else), this
# appends a newline, so
s/\n$// # remove it if that happened.
}
Note that the sed
code depends on the fact that there's only one line that contains "connecting." If there were more such lines, they would be replaced with empty lines because the hold buffer is empty when the second line comes around. It is possible to handle that case, but you'd have to decide what should happen in it. Since you replied in the comments that there's only one such line, I didn't feel the need to guess.
Upvotes: 2
Reputation: 36282
You can try perl, with similar regex syntax than sed but far more powerful for theses issues. It simply set a flag when at least one substitution has been done. After parsing the whole file, in the END {}
block, add the comment if the $flag
variable has not been set:
perl -pe '
s/^.*connecting.*$/Import a text file by opening it/ and $done = 1;
END { printf qq|%s\n|, q|Import a text file by opening it| unless $done }
' infile
When the line is found, it yields:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
When it's not found, it yields:
What do you want to do?
Import a text file by opening it in Excel
Export data to a text file by saving it
Change the delimiter that is used in a text file
Change the separator in all .csv text files
Import a text file by opening it
If it appears more than once, change both but it doesn't append anything:
What do you want to do?
Import a text file by opening it in Excel
Import a text file by opening it
Export data to a text file by saving it
Change the delimiter that is used in a text file
Import a text file by opening it
Change the separator in all .csv text files
Upvotes: 0