What I Learnt Today 2022-01-20

在 Windows WSL 命令行中读写 Windows 系统剪切板

在 Shell 配置文件(例如 ~/.bashrc, ~/.zshrc )中添加如下代码:

1
2
alias pbcopy="/mnt/c/Windows/System32/clip.exe"
alias pbpaste="/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -command 'Get-Clipboard' | sed -e 's/\r\n$//g'"

然后就可以 WSL 中用 pbpaste 读取 Windows 系统剪切板中的内容,使用 pbcopy 来向 Windows 系统剪切板写入内容。

使用 pbpaste 时如果发现读取到的文本是乱码,那可能是由于 WSL 和 Windows 的系统字符编码不一致造成的,可以通过这个命令来解决乱码问题:

1
pbpaste | iconv -f GBK

应用实例

  1. 假设从浏览器或 Fiddler 中复制了 HTTP 接口的响应 JSON 如下:

    1
    {"jsonapi":{"version":"1.0"},"errors":[{"code":"123","source":{"pointer":"/data/attributes/first-name"},"title":"Value is too short","detail":"First name must contain at least three characters."},{"code":"225","source":{"pointer":"/data/attributes/password"},"title":"Passwords must contain a letter, number, and punctuation character.","detail":"The password provided is missing a punctuation character."},{"code":"226","source":{"pointer":"/data/attributes/password"},"title":"Password and password confirmation do not match."}]}
  2. 在 WSL 命令行中可以这样来对这种单行的 compact JSON 进行格式化:

    1
    pbpaste | jq

    输出如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    {
    "jsonapi": {
    "version": "1.0"
    },
    "errors": [
    {
    "code": "123",
    "source": {
    "pointer": "/data/attributes/first-name"
    },
    "title": "Value is too short",
    "detail": "First name must contain at least three characters."
    },
    {
    "code": "225",
    "source": {
    "pointer": "/data/attributes/password"
    },
    "title": "Passwords must contain a letter, number, and punctuation character.",
    "detail": "The password provided is missing a punctuation character."
    },
    {
    "code": "226",
    "source": {
    "pointer": "/data/attributes/password"
    },
    "title": "Password and password confirmation do not match."
    }
    ]
    }
  3. 也可以提取 JSON 中特定路径下的内容,比如要提取最后一条错误信息( errors 字段)的 code 的值:

    1
    pbpaste | jq .errors[-1].code

    其中 -1 作为数组的索引时,表示数组的最后一个元素,这个用法和 Python 等语言的列表/数组取最后一个元素的用法是一样的。

  4. 如果想判断错误信息中的哪个字段包含了 password 字样,可以使用 gron 这个工具, gron 会将 JSON 数据转换为下面这种形式:

    json = {};
    json.errors = [];
    json.errors[0] = {};
    json.errors[0].code = "123";
    json.errors[0].detail = "First name must contain at least three characters.";
    json.errors[0].source = {};
    json.errors[0].source.pointer = "/data/attributes/first-name";
    json.errors[0].title = "Value is too short";
    json.errors[1] = {};
    json.errors[1].code = "225";
    json.errors[1].detail = "The password provided is missing a punctuation character.";
    json.errors[1].source = {};
    json.errors[1].source.pointer = "/data/attributes/password";
    json.errors[1].title = "Passwords must contain a letter, number, and punctuation character.";
    json.errors[2] = {};
    json.errors[2].code = "226";
    json.errors[2].source = {};
    json.errors[2].source.pointer = "/data/attributes/password";
    json.errors[2].title = "Password and password confirmation do not match.";
    json.jsonapi = {};
    json.jsonapi.version = "1.0";

    然后我们结合 grep 来对结果进行搜索:

    1
    pbpaste | gron | grep 'password'