Reputation: 347
Given the following file.txt
:
this is line 1
# this is line 2
this is line 3
I would like to use sed to replace the lines with #
at the beginning with \e[31m${lineContent}\e[0m
. This will color that particular line. Additionally, I need the color \e[31m
to be in a variable, color
. (The desired output of this example would be having the second line colored). I have the following:
function colorLine() {
cat file.txt | sed ''/"$1"/s//"$(printf \e[31m $1 \e[0m)"/g''
}
colorLine "#.*"
The variable color
is not included in what I have so far, as I am not sure how to go about that part.
The output of this is (with the second line being red):
this is line 1
#.*
this is line 3
It is apparently interpreting the replace string literally. My question is how do I use the matched line to generate the replace string?
I understand that I could do something much easier like appending \e[31m
to the beginning of all lines that start with #
, but it is important to use sed with the regexes.
Upvotes: 1
Views: 337
Reputation: 755016
colorLine() {
sed "/$1/s//"$'\e[31m&\e[0m/' file.txt
}
colorLine "#.*"
Multiple fixes, but it uses $1
to identify the pattern from the arguments to the function, and then uses ANSI-C quoting to encode the escape sequences — and fixes the color reset sequence which was (originally) missing the [
after the escape sequence. It also avoids the charge of "UUoC — Useless Use of cat
".
The fixed file name is not exactly desirable, but fixing it is left as an exercise for the reader.
What if I needed
\e[31m
to be a variable,$color
. How do I change the quoting?
I have a colour-diff
script which contains (in Perl notation — I've translated it to Bash notation using ANSI C quoting as before):
reset=$'\e[0m'
black=$'\e[30;1m' # 30 = Black, 1 = bold
red=$'\e[31;1m' # 31 = Red, 1 = bold
green=$'\e[32;1m' # 32 = Green, 1 = bold
yellow=$'\e[33;1m' # 33 = Yellow, 1 = bold
blue=$'\e[34;1m' # 34 = Blue, 1 = bold
magenta=$'\e[35;1m' # 35 = Magenta, 1 = bold
cyan=$'\e[36;1m' # 36 = Cyan, 1 = bold
white=$'\e[37;1m' # 37 = White, 1 = bold
With those variables around, you can create your function as you wish:
colorLine() {
sed "/$1/s//$blue&$reset/“ file.txt
}
Where you set those variables depends on where you define your function. For myself, I'd probably make a script rather than a function, with full-scale argument parsing, and go from there. YMMV
Take a look at List of ANSI color escape sequences to get a more comprehensive list of colours (and other effects — including background and foreground colours) and the escape sequence used to generate it.
Upvotes: 4
Reputation: 41460
An awk
version
black='\033[30;1m'
red='\033[31;1m'
green='\033[32;1m'
yellow='\033[33;1m'
blue='\033[34;1m'
magenta='\033[35;1m'
cyan='\033[36;1m'
white='\033[37;1m'
color=$cyan
colorLine() { awk -v s="$1" -v c=$color '$0~s {$0=c$0"\033[0m"}1' file.txt; }
colorLine "#.*"
You can add file as a variable as vell:
color=$cyan
file="file.txt"
colorLine() { awk -v s="$1" -v c=$color '$0~s {$0=c$0"\033[0m"}1' $file; }
colorLine "#.*"
In awk
\e
is printed as \033
A more dynamic version:
colorLine() {
temp=$2;
col=${!temp};
awk -v s="$1" -v c=$col '$0~s {$0=c$0"\033[0m"}1' $3; }
colorLine "#.*" green file.txt
Then you have colorLine pattern color file
Upvotes: 0
Reputation: 19675
I'd trick grep to do it for me this way:
function colorLine() {
GREP_COLORS="mt=31" grep --color=always --context=$(wc -l <file.txt) --no-filename "$1" file.txt
}
Split-out of the trick:
GREP_COLORS="mt=31"
: SGR substring for matching non-empty text in any matching line. Here will generate \e[31m
red before matched string, and reset to default color after matched string.
--color=always
: always colorise even in non interactive shell
context=$(wc -l <file.txt)
: output as much context lines as number of lines in the file (so all lines).
--no-filename
: do not print the file name
Upvotes: 0
Reputation: 88939
With GNU sed and Kubuntu 16.04.
foo="#.*"
sed 's/'"$foo"'/\x1b[31m&\x1b[0m/' file
Upvotes: 1