V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
leverestfish
V2EX  ›  程序员

[求助] zsh 使用 open 命令打开含中文 url 失败

  •  
  •   leverestfish · Dec 12, 2020 · 1698 views
    This topic created in 1965 days ago, the information mentioned may be changed or developed.

    之前一直用一个 Alfred workflow 来实现选中文字快速百度查询,是通过一个 zsh 脚本的 open 命令来打开链接的,更新 Big Sur 之后这个 workflow 跪了,看了下是由于无法用 open 命令来打开含有中文字符的 URL 来,具体情况见下图。

    shell 小白在这问下有没有什么解决方案,比如如何把$url 变量进行 urlencode 等,或者是否有 open 的替代命令?

    另外也好奇为什么会出这个问题。

    图片

    # 打开英文 url 是 OK 的
    url="abcd"
    open http://www.baidu.com/s\?wd\=$url
    
    # 有中文就报错了(识别为系统文件了)
    url="汉字"
    open http://www.baidu.com/s\?wd\=$url
    The file /Users/<my_username>/http:/www.baidu.com/s?wd=汉字 does not exist.
    

    尝试了加引号等操作均没有办法(实在是 shell 小白了),并且已善用搜索,求大佬指点,谢谢!

    dorentus
        1
    dorentus  
       Dec 12, 2020   ❤️ 1
    URLEncode 一下。。。

    url="汉字"
    open http://www.baidu.com/s\?wd\=$(perl -MURI::Escape -le "print uri_escape('$url')")

    ----

    解释:

    下面这行 perl 命令会对 $url 进行 URLEncode (这是我在 macOS 下面能找到的不安装任何包就能用的最快的 URLEncode 了):

    perl -MURI::Escape -le "print uri_escape('$url')"

    而 Bash 的 $(命令) 会把命令输出的结果转化成字符串

    其实也相当于:

    url="汉字"
    url_encoded=$(perl -MURI::Escape -le "print uri_escape('$url')")
    open http://www.baidu.com/s\?wd\=$url_encoded
    Jirajine
        2
    Jirajine  
       Dec 12, 2020 via Android   ❤️ 1
    omz_urlencode () {
    emulate -L zsh
    zparseopts -D -E -a opts r m P
    local in_str=$1
    local url_str=""
    local spaces_as_plus
    if [[ -z $opts[(r)-P] ]]
    then
    spaces_as_plus=1
    fi
    local str="$in_str"
    local encoding=$langinfo[CODESET]
    local safe_encodings
    safe_encodings=(UTF-8 utf8 US-ASCII)
    if [[ -z ${safe_encodings[(r)$encoding]} ]]
    then
    str=$(echo -E "$str" | iconv -f $encoding -t UTF-8)
    if [[ $? != 0 ]]
    then
    echo "Error converting string from $encoding to UTF-8" >&2
    return 1
    fi
    fi
    local i byte ord LC_ALL=C
    export LC_ALL
    local reserved=';/?:@&=+$,'
    local mark='_.!~*''()-'
    local dont_escape="[A-Za-z0-9"
    if [[ -z $opts[(r)-r] ]]
    then
    dont_escape+=$reserved
    fi
    if [[ -z $opts[(r)-m] ]]
    then
    dont_escape+=$mark
    fi
    dont_escape+="]"
    local url_str=""
    for ((i = 1; i <= ${#str}; ++i )) do
    byte="$str[i]"
    if [[ "$byte" =~ "$dont_escape" ]]
    then
    url_str+="$byte"
    else
    if [[ "$byte" == " " && -n $spaces_as_plus ]]
    then
    url_str+="+"
    else
    ord=$(( [##16] #byte ))
    url_str+="%$ord"
    fi
    fi
    done
    echo -E "$url_str"
    }
    leverestfish
        3
    leverestfish  
    OP
       Dec 12, 2020
    @dorentus
    @Jirajine
    问题解决,感谢二位,学习了!这问题看起来确实有点蠢了,因为我搜 shell 进行 urlencode 发现都是文件操作,所以才来问了,再次感谢~
    aloxaf
        4
    aloxaf  
       Dec 12, 2020   ❤️ 1
    > 另外也好奇为什么会出这个问题。

    这和 zsh 和 shell 都没有半毛钱关系,显然是 open 命令升级后对 url 的判定规则改变了。大概写这个程序员没想过世界上竟然还有包含 non-ascii 字符的 url 。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2442 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 05:10 · PVG 13:10 · LAX 22:10 · JFK 01:10
    ♥ Do have faith in what you're doing.