V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
leverestfish
V2EX  ›  程序员

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

  •  
  •   leverestfish · 2020-12-12 19:19:01 +08:00 · 1244 次点击
    这是一个创建于 1471 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前一直用一个 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  
       2020-12-12 19:40:30 +08:00   ❤️ 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  
       2020-12-12 19:43:26 +08:00 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
       2020-12-12 20:05:49 +08:00
    @dorentus
    @Jirajine
    问题解决,感谢二位,学习了!这问题看起来确实有点蠢了,因为我搜 shell 进行 urlencode 发现都是文件操作,所以才来问了,再次感谢~
    aloxaf
        4
    aloxaf  
       2020-12-12 20:06:53 +08:00   ❤️ 1
    > 另外也好奇为什么会出这个问题。

    这和 zsh 和 shell 都没有半毛钱关系,显然是 open 命令升级后对 url 的判定规则改变了。大概写这个程序员没想过世界上竟然还有包含 non-ascii 字符的 url 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   914 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 19:42 · PVG 03:42 · LAX 11:42 · JFK 14:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.