Highlight the difference in lines

I am looking for a way to highlight the differences between two lines. The idea is to show in the terminal which characters iconv has changed. Both lines have already been processed to remove leading and trailing spaces, but internal spaces need to be handled.

RED="$(tput setaf 1)"    ##    Short variables for the tput ->
CYA="$(tput setaf 6)"    ## -> commands to make output strings ->
CLS="$(tput sgr0)"       ## -> easier to read
str1="[String nâmè™]"    # String prior to iconv
str2="[String name[tm]]" # String after iconv -f utf-8 -t ascii//translit

Ultimately, I want to automate the formatting of the differences so that they are surrounded by tput color codes that I can repeat on the terminal.

${str1}= Highlight in red characters that are not common to both lines

${str2}= Highlight blue characters that are not common to both lines

Required Conclusion:

output1="[String n${RED}â${CLS}m${RED}è™${CLS}]"
output2="[String n${CYA}a${CLS}m${CYA}e[tm]${CLS}]"

Most diff utilities I looked at work on line or word level. I was thinking about parsing cmp output for byte # of the first diff, but I would have to re-parse for a few differences. It seems.

, , , , , .

, - , , .

nstr1="$(fold -w1 <<< "$(echo "${str1}")")"
nstr2="$(fold -w1 <<< "$(echo "${str2}")")"
diff <(echo -e "${nstr1}") <(echo -e "${nstr2}")

, , . , , ?

0
2

:

#!/usr/bin/env bash

# Using stdin input, outputs each char. on its own line, with actual newlines
# in the input represented as literal '\n'.
toSingleCharLines() {
  sed 's/\(.\)/\1\'$'\n''/g; s/\n$/\'$'\n''\\n/'
}

# Using stdin input, reassembles a string split into 1-character-per-line output
# by toSingleCharLines().
fromSingleCharLines() {
  awk '$0=="\\n" { printf "\n"; next} { printf "%s", $0 }'
}

# Prints a colored string read from stdin by interpreting embedded color references
# such as '${RED}'.
printColored() {
  local str=$(</dev/stdin)
  local RED="$(tput setaf 1)" CYA="$(tput setaf 6)" RST="$(tput sgr0)"
  str=${str//'${RED}'/${RED}}
  str=${str//'${CYA}'/${CYA}}
  str=${str//'${RST}'/${RST}}
  printf '%s\n' "$str"
}

# The non-ASCII input string.
strOrg='[String nâmè™]'

# Create its ASCII-chars.-only transliteration.
strTransLit=$(iconv -f utf-8 -t ascii//translit <<<"$strOrg")

# Print the ORIGINAL string with the characters that NEED transliteration
# highlighted in RED.
diff --changed-group-format='${RED}%=${RST}' \
  <(toSingleCharLines <<<"$strOrg") <(toSingleCharLines <<<"$strTransLit") |
    fromSingleCharLines | printColored

# Print the TRANSLITERATED string with the characters that RESULT FROM
# transliteration highlighted in CYAN.
diff --changed-group-format='${CYA}%=${RST}' \
  <(toSingleCharLines <<<"$strTransLit") <(toSingleCharLines <<<"$strOrg") |
    fromSingleCharLines | printColored

:

output

+3

, @Thomas Dickey, , , , , .

, , " Wanted Output" diff.

diff --changed-group-format="\${RED}%=\${CLS}" <(echo -e "${nstr1}") <(echo -e "${nstr2}")|tr -d '\n'
diff --changed-group-format="\${CYA}%>\${CLS}" <(echo -e "${nstr1}") <(echo -e "${nstr2}")|tr -d '\n'

, , , .

+1

Source: https://habr.com/ru/post/1621034/


All Articles