{"id":13318,"date":"2026-02-28T15:55:01","date_gmt":"2026-02-28T07:55:01","guid":{"rendered":"https:\/\/www.gbase8.cn\/?p=13318"},"modified":"2026-02-28T15:55:05","modified_gmt":"2026-02-28T07:55:05","slug":"ipv6%e5%9c%b0%e5%9d%80%e5%b1%95%e5%bc%80%e7%ba%afshell%e8%84%9a%e6%9c%ac","status":"publish","type":"post","link":"https:\/\/www.gbase8.cn\/en\/13318","title":{"rendered":"Expand IPv6 Address Pure Shell Script"},"content":{"rendered":"<p>Pure Shell implementation for IPv6 address expansion (reverse formatting), converting compressed format to 8-segment, 4-digit full format. Supports address validity checks and handling of IPv6 addresses with prefixes.<\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Directory Navigation<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a2d50a2075bc\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewbox=\"0 0 24 24\" version=\"1.2\" baseprofile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a2d50a2075bc\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.gbase8.cn\/en\/13318\/#%E7%BA%AFSHELL%E8%84%9A%E6%9C%AC\" >\u7eafSHELL\u811a\u672c<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.gbase8.cn\/en\/13318\/#%E8%BF%90%E8%A1%8C%E6%A0%B7%E4%BE%8B\" >\u8fd0\u884c\u6837\u4f8b<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E7%BA%AFSHELL%E8%84%9A%E6%9C%AC\"><\/span>\u7eafSHELL\u811a\u672c<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>#!\/bin\/bash\r\nset -euo pipefail\r\n\r\n# \u811a\u672c\u540d\u79f0\r\nSCRIPT_NAME=$(basename \"$0\")\r\n\r\n# \u5e2e\u52a9\u4fe1\u606f\u51fd\u6570\r\nshow_help() {\r\n    cat &lt;&lt; EOF\r\n\u7528\u6cd5: $SCRIPT_NAME &#91;\u9009\u9879] &lt;IPv6\u5730\u5740>\r\n\r\n\u529f\u80fd: \u7eafShell\u5b9e\u73b0IPv6\u5730\u5740\u5c55\u5f00\uff08\u53cd\u5411\u683c\u5f0f\u5316\uff09\uff0c\u5c06\u538b\u7f29\u683c\u5f0f\u8f6c\u4e3a8\u6bb54\u4f4d\u5b8c\u6574\u683c\u5f0f\r\n      \u652f\u6301\u9a8c\u8bc1\u5730\u5740\u6709\u6548\u6027\u3001\u5904\u7406\u5e26\u524d\u7f00\u7684IPv6\u5730\u5740\r\n\r\n\u9009\u9879:\r\n    -h, --help      \u663e\u793a\u6b64\u5e2e\u52a9\u4fe1\u606f\u5e76\u9000\u51fa\r\n    -p, --prefix    \u4fdd\u7559IPv6\u5730\u5740\u7684\u524d\u7f00\uff08\u59822001:db8::1\/64\uff09\uff0c\u9ed8\u8ba4\u4ec5\u5c55\u5f00\u5730\u5740\u90e8\u5206\r\n\r\n\u793a\u4f8b:\r\n    $SCRIPT_NAME 2001:db8::1\r\n    $SCRIPT_NAME -p ::1\/128\r\n    $SCRIPT_NAME fe80::1234:5678:9abc:def0\r\nEOF\r\n}\r\n\r\n# \u9a8c\u8bc1IPv6\u5730\u5740\u5b57\u7b26\u5408\u6cd5\u6027\uff08\u57fa\u7840\u6821\u9a8c\uff09\r\nvalidate_ipv6_chars() {\r\n    local addr=\"$1\"\r\n    # IPv6\u5408\u6cd5\u5b57\u7b26\uff1a0-9, a-f, A-F, :, \/\uff08\u524d\u7f00\uff09\r\n    if &#91;&#91; ! \"$addr\" =~ ^&#91;0-9a-fA-F:\/]+$ ]]; then\r\n        echo \"\u9519\u8bef: IPv6\u5730\u5740\u5305\u542b\u975e\u6cd5\u5b57\u7b26\uff08\u4ec5\u5141\u8bb80-9\/a-f\/A-F\/:\/\uff09\" >&amp;2\r\n        exit 1\r\n    fi\r\n}\r\n\r\n# \u6838\u5fc3\uff1a\u5c55\u5f00IPv6\u5730\u5740\u4e3a8\u6bb54\u4f4d\u5b8c\u6574\u683c\u5f0f\r\nexpand_ipv6_core() {\r\n    local pure_addr=\"$1\"\r\n    local expanded_segments=()\r\n    \r\n    # \u6b65\u9aa41\uff1a\u68c0\u67e5::\u51fa\u73b0\u7684\u6b21\u6570\uff08\u5408\u6cd5IPv6\u53ea\u80fd\u6709\u4e00\u4e2a::\uff09\r\n    local colon_count=$(grep -o \"::\" &lt;&lt;&lt; \"$pure_addr\" | wc -l)\r\n    if &#91;&#91; $colon_count -gt 1 ]]; then\r\n        echo \"\u9519\u8bef: \u65e0\u6548\u7684IPv6\u5730\u5740\uff08::\u53ea\u80fd\u51fa\u73b0\u4e00\u6b21\uff09\" >&amp;2\r\n        exit 1\r\n    fi\r\n\r\n    # \u6b65\u9aa42\uff1a\u5904\u7406\u5168\u96f6\u538b\u7f29\uff08::\uff09\r\n    if &#91;&#91; \"$pure_addr\" == \"::\" ]]; then\r\n        echo \"0000:0000:0000:0000:0000:0000:0000:0000\"\r\n        return\r\n    fi\r\n\r\n    # \u6b65\u9aa43\uff1a\u66ff\u6362::\u4e3a\u4e34\u65f6\u6807\u8bb0\uff0c\u62c6\u5206\u5730\u5740\u6bb5\r\n    local temp_addr=\"${pure_addr\/\/::\/:__ZERO__:}\"\r\n    # \u6b63\u786e\u62c6\u5206\u5730\u5740\u6bb5\uff08IFS=: \u751f\u6548\uff09\r\n    local segments=()\r\n    IFS=: read -ra segments &lt;&lt;&lt; \"$temp_addr\"\r\n    \r\n    # \u8fc7\u6ee4\u7a7a\u6bb5\uff08\u5904\u7406\u5f00\u5934\/\u7ed3\u5c3e\u7684::\uff09\r\n    local filtered_segments=()\r\n    for seg in \"${segments&#91;@]}\"; do\r\n        if &#91;&#91; -n \"$seg\" ]]; then\r\n            filtered_segments+=(\"$seg\")\r\n        fi\r\n    done\r\n    segments=(\"${filtered_segments&#91;@]}\")\r\n\r\n    # \u6b65\u9aa44\uff1a\u8ba1\u7b97\u9700\u8981\u8865\u5145\u76840\u6bb5\u6570\uff08\u603b\u6bb5\u6570\u9700\u4e3a8\uff09\r\n    local zero_pos=-1\r\n    local seg_count=${#segments&#91;@]}\r\n    for i in \"${!segments&#91;@]}\"; do\r\n        if &#91;&#91; \"${segments&#91;$i]}\" == \"__ZERO__\" ]]; then\r\n            zero_pos=$i\r\n            break\r\n        fi\r\n    done\r\n\r\n    # \u6b65\u9aa45\uff1a\u6784\u5efa\u5c55\u5f00\u540e\u7684\u6bb5\u5217\u8868\uff08\u5148\u586b\u5145\u539f\u59cb\u6bb5\uff0c\u518d\u8865\u5145\u96f6\u6bb5\uff09\r\n    local new_segments=()\r\n    if &#91;&#91; $zero_pos -ne -1 ]]; then\r\n        # \u8ba1\u7b97\u9700\u8981\u586b\u5145\u76840\u6bb5\u6570\r\n        local fill_zeros=$((8 - (seg_count - 1)))\r\n        if &#91;&#91; $fill_zeros -lt 0 ]]; then\r\n            echo \"\u9519\u8bef: IPv6\u5730\u5740\u6bb5\u6570\u8fc7\u591a\uff08\u8d85\u8fc78\u6bb5\uff09\" >&amp;2\r\n            exit 1\r\n        fi\r\n        # \u62fc\u63a5\u524d\u534a\u6bb5\r\n        for ((i=0; i&lt;zero_pos; i++)); do\r\n            new_segments+=(\"${segments&#91;$i]}\")\r\n        done\r\n        # \u586b\u51450\u6bb5\uff08\u5148\u586b\u7a7a\u5b57\u7b26\u4e32\uff0c\u540e\u7eed\u8865\u96f6\uff09\r\n        for ((i=0; i&lt;fill_zeros; i++)); do\r\n            new_segments+=(\"\")\r\n        done\r\n        # \u62fc\u63a5\u540e\u534a\u6bb5\r\n        for ((i=zero_pos+1; i&lt;seg_count; i++)); do\r\n            new_segments+=(\"${segments&#91;$i]}\")\r\n        done\r\n    else\r\n        # \u65e0::\u7684\u60c5\u51b5\uff0c\u76f4\u63a5\u4f7f\u7528\u539f\u6bb5\uff08\u9700\u6b63\u597d8\u6bb5\uff09\r\n        new_segments=(\"${segments&#91;@]}\")\r\n        if &#91;&#91; ${#new_segments&#91;@]} -ne 8 ]]; then\r\n            echo \"\u9519\u8bef: IPv6\u5730\u5740\u6bb5\u6570\u9519\u8bef\uff08\u65e0::\u65f6\u9700\u6b63\u597d8\u6bb5\uff09\" >&amp;2\r\n            exit 1\r\n        fi\r\n    fi\r\n\r\n    # \u6b65\u9aa46\uff1a\u9a8c\u8bc1\u6bcf\u6bb5\u5e76\u8865\u96f6\u52304\u4f4d\uff08\u6838\u5fc3\u5c55\u5f00\u903b\u8f91\uff09\r\n    for seg in \"${new_segments&#91;@]}\"; do\r\n        # \u7a7a\u6bb5\/\u96f6\u6bb5\u5904\u7406\u4e3a0000\r\n        if &#91;&#91; -z \"$seg\" || \"$seg\" == \"0\" ]]; then\r\n            expanded_segments+=(\"0000\")\r\n            continue\r\n        fi\r\n\r\n        # \u9a8c\u8bc1\u6bb5\u957f\u5ea6\uff08\u6700\u591a4\u4f4d\uff09\r\n        if &#91;&#91; ${#seg} -gt 4 ]]; then\r\n            echo \"\u9519\u8bef: IPv6\u5730\u5740\u6bb5 '$seg' \u8fc7\u957f\uff08\u6700\u591a4\u4f4d\uff09\" >&amp;2\r\n            exit 1\r\n        fi\r\n\r\n        # \u9a8c\u8bc1\u662f\u5408\u6cd516\u8fdb\u5236\u6570\r\n        if ! &#91;&#91; \"$seg\" =~ ^&#91;0-9a-fA-F]{1,4}$ ]]; then\r\n            echo \"\u9519\u8bef: IPv6\u5730\u5740\u6bb5 '$seg' \u5305\u542b\u975e\u6cd5\u5b57\u7b26\" >&amp;2\r\n            exit 1\r\n        fi\r\n\r\n        # \u8865\u96f6\u52304\u4f4d\uff08\u7528bc\u5de5\u5177\u786e\u4fdd16\u8fdb\u5236\u8865\u96f6\uff0c\u517c\u5bb9\u5927\u5c0f\u5199\uff09\r\n        # \u5148\u8f6c\u5927\u5199\u2192\u8f6c10\u8fdb\u5236\u2192\u8f6c16\u8fdb\u5236\u2192\u8865\u524d\u5bfc\u96f6\u52304\u4f4d\u2192\u8f6c\u5c0f\u5199\uff08\u53ef\u9009\uff0c\u4fdd\u6301\u8f93\u5165\u5927\u5c0f\u5199\u4e5f\u53ef\uff09\r\n        local seg_upper=$(echo \"$seg\" | tr 'a-f' 'A-F')\r\n        local seg_10=$(echo \"ibase=16; $seg_upper\" | bc)\r\n        local seg_4digit=$(printf \"%04x\" \"$seg_10\" | tr 'A-F' 'a-f')\r\n        expanded_segments+=(\"$seg_4digit\")\r\n    done\r\n\r\n    # \u6b65\u9aa47\uff1a\u62fc\u63a5\u4e3a8\u6bb5\u5b8c\u6574\u5730\u5740\r\n    local expanded_addr=$(IFS=:; echo \"${expanded_segments&#91;*]}\")\r\n    echo \"$expanded_addr\"\r\n}\r\n\r\n# \u4e3b\u51fd\u6570\uff1a\u5904\u7406\u524d\u7f00+\u8c03\u7528\u6838\u5fc3\u5c55\u5f00\u903b\u8f91\r\nexpand_ipv6() {\r\n    local addr=\"$1\"\r\n    local keep_prefix=\"$2\"\r\n    local pure_addr\r\n    local prefix=\"\"\r\n\r\n    # \u5206\u79bb\u5730\u5740\u548c\u524d\u7f00\r\n    if &#91;&#91; \"$addr\" =~ \/ ]]; then\r\n        pure_addr=\"${addr%\/*}\"\r\n        prefix=\"${addr#*\/}\"\r\n        # \u9a8c\u8bc1\u524d\u7f00\u5408\u6cd5\u6027\uff080-128\u7684\u6574\u6570\uff09\r\n        if ! &#91;&#91; \"$prefix\" =~ ^&#91;0-9]+$ ]] || &#91;&#91; \"$prefix\" -lt 0 ]] || &#91;&#91; \"$prefix\" -gt 128 ]]; then\r\n            echo \"\u9519\u8bef: \u65e0\u6548\u7684IPv6\u524d\u7f00 '$prefix'\uff08\u9700\u4e3a0-128\u7684\u6574\u6570\uff09\" >&amp;2\r\n            exit 1\r\n        fi\r\n    else\r\n        pure_addr=\"$addr\"\r\n    fi\r\n\r\n    # \u57fa\u7840\u5b57\u7b26\u9a8c\u8bc1\r\n    validate_ipv6_chars \"$pure_addr\"\r\n\r\n    # \u8c03\u7528\u6838\u5fc3\u5c55\u5f00\u903b\u8f91\r\n    local expanded_addr=$(expand_ipv6_core \"$pure_addr\")\r\n\r\n    # \u62fc\u63a5\u524d\u7f00\uff08\u5982\u679c\u9700\u8981\uff09\r\n    if &#91;&#91; \"$keep_prefix\" -eq 1 &amp;&amp; -n \"$prefix\" ]]; then\r\n        echo \"${expanded_addr}\/${prefix}\"\r\n    else\r\n        echo \"$expanded_addr\"\r\n    fi\r\n}\r\n\r\n# \u89e3\u6790\u547d\u4ee4\u884c\u53c2\u6570\r\nKEEP_PREFIX=0\r\nIPV6_ADDR=\"\"\r\n\r\nwhile &#91;&#91; $# -gt 0 ]]; do\r\n    case \"$1\" in\r\n        -h|--help)\r\n            show_help\r\n            exit 0\r\n            ;;\r\n        -p|--prefix)\r\n            KEEP_PREFIX=1\r\n            shift\r\n            ;;\r\n        *)\r\n            if &#91;&#91; -z \"$IPV6_ADDR\" ]]; then\r\n                IPV6_ADDR=\"$1\"\r\n                shift\r\n            else\r\n                echo \"\u9519\u8bef: \u591a\u4f59\u7684\u53c2\u6570 '$1'\" >&amp;2\r\n                show_help >&amp;2\r\n                exit 1\r\n            fi\r\n            ;;\r\n    esac\r\ndone\r\n\r\n# \u68c0\u67e5\u662f\u5426\u8f93\u5165\u4e86IPv6\u5730\u5740\r\nif &#91;&#91; -z \"$IPV6_ADDR\" ]]; then\r\n    echo \"\u9519\u8bef: \u5fc5\u987b\u6307\u5b9aIPv6\u5730\u5740\" >&amp;2\r\n    show_help >&amp;2\r\n    exit 1\r\nfi\r\n\r\n# \u6267\u884c\u5c55\u5f00\u5e76\u8f93\u51fa\u7ed3\u679c\r\nexpand_ipv6 \"$IPV6_ADDR\" \"$KEEP_PREFIX\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E8%BF%90%E8%A1%8C%E6%A0%B7%E4%BE%8B\"><\/span>\u8fd0\u884c\u6837\u4f8b<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>&#91;gbase@vm151 ~]$ .\/ipv6_expand.sh -p 2001:1::5:0:0:8\/64\r\n2001:0001:0000:0000:0005:0000:0000:0008\/64\r\n&#91;gbase@vm151 ~]$ .\/ipv6_expand.sh 2001:1::5:0:0:8\r\n2001:0001:0000:0000:0005:0000:0000:0008\r\n<\/code><\/pre>\n\n\n\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>Pure Shell implementation for IPv6 address expansion (reverse formatting), converting compressed format to 8-segment, 4-digit full format. Supports address validity checks and handling of IPv6 addresses with prefixes.<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[58,72],"class_list":["post-13318","post","type-post","status-publish","format-standard","hentry","category-1","tag-ipv6","tag-linux"],"_links":{"self":[{"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/posts\/13318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/comments?post=13318"}],"version-history":[{"count":1,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/posts\/13318\/revisions"}],"predecessor-version":[{"id":13319,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/posts\/13318\/revisions\/13319"}],"wp:attachment":[{"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/media?parent=13318"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/categories?post=13318"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gbase8.cn\/en\/wp-json\/wp\/v2\/tags?post=13318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}