Bash脚本将HTML实体转换为字符

我正在寻找一种方法来解决这个问题:

hello < world

对此:

hello < world

我可以使用sed,但是如何在不使用神秘正则表达式的情况下实现呢?

Marko asked 2019-11-08T11:41:56Z
7个解决方案
80 votes

尝试重新编码(存档页面; GitHub镜像; Debian页面):

$ echo '&lt;' |recode html..ascii
<

在Linux和类似的Unix-y系统上安装:

$ sudo apt-get install recode

使用以下命令在Mac OS上安装:

$ brew install recode
ceving answered 2019-11-08T11:42:26Z
45 votes

使用perl:

cat foo.html | perl -MHTML::Entities -pe 'decode_entities($_);'

从命令行使用php:

cat foo.html | php -r 'while(($line=fgets(STDIN)) !== FALSE) echo html_entity_decode($line, ENT_QUOTES|ENT_HTML401);'
user1788934 answered 2019-11-08T11:42:57Z
18 votes

一种替代方法是通过Web浏览器进行管道传输,例如:

echo '&#33;' | w3m -dump -T text/html

在cygwin中,这对我非常有用,因为在cygwin中,下载和安装发行版很困难。

在这里找到这个答案

Whitecat answered 2019-11-08T11:43:42Z
16 votes

使用xmlstarlet:

echo 'hello &lt; world' | xmlstarlet unesc
user243 answered 2019-11-08T11:44:06Z
9 votes

该答案基于:在Bash中转义HTML的简便方法? 可以很好地用于在Stack Exchange上获取答案(使用sed)并将HTML转换为常规ASCII字符:

sed 's/&nbsp;/ /g; s/&amp;/\&/g; s/&lt;/\</g; s/&gt;/\>/g; s/&quot;/\"/g; s/#&#39;/\'"'"'/g; s/&ldquo;/\"/g; s/&rdquo;/\"/g;'

编辑1:2017年4月7日-添加了左双引号和右双引号转换。 这是bash脚本的一部分,可在网络上抓取SE并将其与本地代码文件进行比较:Ask Ubuntu-  本地文件和Ubuntu问答之间的代码版本控制


编辑2017年6月26日

使用sed大约需要3秒钟,才能从Ask Ubuntu / Stack Exchange将1K行文件中的HTML转换为ASCII。 因此,我被迫使用Bash内置搜索并替换大约1秒钟的响应时间。

功能如下:

#-------------------------------------------------------------------------------
LineOut=""      # Make global
HTMLtoText () {
    LineOut=$1  # Parm 1= Input line
    # Replace external command: Line=$(sed 's/&amp;/\&/g; s/&lt;/\</g; 
    # s/&gt;/\>/g; s/&quot;/\"/g; s/&#39;/\'"'"'/g; s/&ldquo;/\"/g; 
    # s/&rdquo;/\"/g;' <<< "$Line") -- With faster builtin commands.
    LineOut="${LineOut//&nbsp;/ }"
    LineOut="${LineOut//&amp;/&}"
    LineOut="${LineOut//&lt;/<}"
    LineOut="${LineOut//&gt;/>}"
    LineOut="${LineOut//&quot;/'"'}"
    LineOut="${LineOut//&#39;/"'"}"
    LineOut="${LineOut//&ldquo;/'"'}" # TODO: ASCII/ISO for opening quote
    LineOut="${LineOut//&rdquo;/'"'}" # TODO: ASCII/ISO for closing quote
} # HTMLtoText ()
WinEunuuchs2Unix answered 2019-11-08T11:45:04Z
5 votes

python 3.2+版本:

cat foo.html | python3 -c 'import html, sys; [print(html.unescape(l), end="") for l in sys.stdin]'
Aissen answered 2019-11-08T11:45:30Z
0 votes

要仅使用sed替换来支持所有HTML实体的转义,将需要太长的命令列表才能使用,因为每个Unicode代码点都至少具有两个相应的HTML实体。

但可以仅使用sed,grep,Bourne shell和基本的UNIX实用程序(GNU coreutils或同等功能)来完成:

#!/bin/sh

htmlEscDec2Hex() {
    file=$1
    [ ! -r "$file" ] && file=$(mktemp) && cat >"$file"

    printf -- \
        "$(sed 's/\\/\\\\/g;s/%/%%/g;s/&#[0-9]\{1,10\};/\&#x%x;/g' "$file")\n" \
        $(grep -o '&#[0-9]\{1,10\};' "$file" | tr -d '&#;')

    [ x"$1" != x"$file" ] && rm -f "$file"
}

htmlHexUnescape() {
    printf -- "$(
        sed 's/\\/\\\\/g;s/%/%%/g
            ;s/&#x\([0-9a-fA-F]\{1,8\}\);/\&#x0000000\1;/g
            ;s/&#x0*\([0-9a-fA-F]\{4\}\);/\\u\1/g
            ;s/&#x0*\([0-9a-fA-F]\{8\}\);/\\U\1/g' )\n"
}

htmlEscDec2Hex "$1" | htmlHexUnescape \
    | sed -f named_entities.sed

但是请注意,需要一个支持\uHHHHhtmlHexUnescape序列的printf实现,例如GNU实用程序。 要进行测试,例如检查&#xH;打印\u。要调用实用程序而不是内置的shell,请用2605096409284284215812替换出现的\U

该脚本使用附加文件htmlHexUnescape,以支持命名实体。 可以使用以下HTML页面根据规范生成它:

<!DOCTYPE html>
<head><meta charset="utf-8" /></head>
<body>
<p id="sed-script"></p>
<script type="text/javascript">
  const referenceURL = 'https://html.spec.whatwg.org/entities.json';

  function writeln(element, text) {
    element.appendChild( document.createTextNode(text) );
    element.appendChild( document.createElement("br") );
  }

  (async function(container) {
    const json = await (await fetch(referenceURL)).json();
    container.innerHTML = "";
    writeln(container, "#!/usr/bin/sed -f");
    const addLast = [];
    for (const name in json) {
      const characters = json[name].characters
        .replace("\\", "\\\\")
        .replace("/", "\\/");
      const command = "s/" + name + "/" + characters + "/g";
      if ( name.endsWith(";") ) {
        writeln(container, command);
      } else {
        addLast.push(command);
      }
    }
    for (const command of addLast) { writeln(container, command); }
  })( document.getElementById("sed-script") );
</script>
</body></html>

只需在现代浏览器中打开它,然后将结果页面另存为htmlHexUnescape作为文本即可。 在这种情况下,给它授予可执行权限很方便,以便可以直接调用它。

现在,上面的shell脚本可以用作htmlHexUnescape,或在从标准输入读取管道的内部。

例如,如果出于某种原因需要按块处理数据(如果2605096409284284215808不是内置的Shell且要处理的数据很大,则可能是这种情况),可以将其用作:

nLines=20
seq 1 $nLines $(grep -c $ "$inputFile") | while read n
    do sed -n "$n,$((n+nLines-1))p" "$inputFile" | ./html_unescape.sh
done

脚本说明如下。

需要支持三种类型的转义序列:

  1. htmlHexUnescape,其中&#xH;是转义字符的Unicode代码点的十进制值;

  2. htmlHexUnescape,其中&#xH;是转义字符的Unicode代码点的十六进制值;

  3. htmlHexUnescape,其中&#xH;是转义字符的命名实体之一的名称。

htmlHexUnescape转义由生成的&#xH;脚本支持,该脚本仅执行替换列表。

这种支持代码点转义的方法的核心是htmlHexUnescape实用程序,该实用程序能够:

  1. 以十六进制格式打印数字,以及

  2. 从代码点的十六进制值打印字符(使用转义字符htmlHexUnescape或2605096409284215215809)。

第一个功能在sed和grep的帮助下,用于将htmlHexUnescape转义符减少为&#xH;809转义符。 外壳函数\u做到了。

函数htmlHexUnescape使用sed将&#xH;转义符转换为printf的2605096409284215815810/\U转义符,然后使用第二个功能来打印未转义的字符。

unagi answered 2019-11-08T11:48:05Z
translate from https://stackoverflow.com:/questions/5929492/bash-script-to-convert-from-html-entities-to-characters