这是一些示例代码:
{"key_code":"a"},
{"key_code":"B"},
{"key_code":"c"},
{"key_code":"D"}
这就是我想做的:
{"key_code":"a"},
{"key_code":"b","modifiers":"left_shift"},
{"key_code":"c"},
{"key_code":"d","modifiers":"left_shift"}
在我的 IDE 中,我可以对 进行区分大小写的搜索"([A-Z])"
并替换为"\L$1", "modifiers": "left_shift"
,但我似乎无法在我的 bash 脚本中使用它。
我使用的是 Mac OS X,所以我认为这\L
给我带来了麻烦。
我尝试过几个版本:
sed -i "" 's/"([A-Z])"/"\L$1","modifiers": "left_shift"/g' file
和
sed -i "" "s/\"([A-Z])\"/\"\L$1\",\"modifiers\": \"left_shift\"/g" file
但没有运气。试图绊倒awk
,但我似乎无法弄清楚......
答案1
在 Macos 上发现的FreeBSDsed
不支持\L
替换 AFAIK。您始终可以使用perl
:
perl -pi -e 's/"\p{Lu}"/\L$&,"modifiers":"left_shift"/g' file
添加-C
选项以同时处理 UTF-8 编码的非 ASCII 大写字母(例如Ê
、Ç
、Ξ
等)。
答案2
假设您显示的 JSON 对象是顶级数组的一部分,如下所示(请注意,键和值之外的空格字符无关):
[
{
"key_code": "a"
},
{
"key_code": "B"
},
{
"key_code": "c"
},
{
"key_code": "D"
}
]
然后我们可以测试每个key_code
值是否为大写,如果是,则将 添加modifiers
到该对象:
jq '(.[] | select(.key_code | test("[[:upper:]]"))) += { "modifiers": "left_shift" }' file
或者,或者(但稍微短一些),
jq '(.[] | select(.key_code | test("[[:upper:]]"))).modifiers |= "left_shift"' file
map()
或者,在最顶层的数组上使用,
jq 'map(select(.key_code | test("[[:upper:]]")).modifiers |= "left_shift")' file
根据问题中的给定输入,这将产生以下输出:
[
{
"key_code": "a"
},
{
"key_code": "B",
"modifiers": "left_shift"
},
{
"key_code": "c"
},
{
"key_code": "D",
"modifiers": "left_shift"
}
]
如果数组保存在较大的 JSON 文档中的其他位置,则只需更改表达式.[]
中的首字母jq
,以便提取相关元素(最后一个示例表达式 with map()
,显然需要其他更改)。
答案3
如果输入每次都看起来完全一样,这应该足够了:
awk '{if(/:"[A-Z]"/) sub(/"}/, "\",\"modifiers\":\"left_shift\"}"); print tolower($0) }' inputfile > outputfile
另一种选择可能是这样的:
sed 's/"[A-Z]"/&,"modifiers": "left_shift"/g' inputfile | tr '[[:upper:]]' '[[:lower:]]' > outputfile
无法在 Mac 上测试,但似乎足够通用,应该可以工作。
tolower($0)
和命令都会tr
以小写形式返回所有内容,这可能是也可能不是所需的,因此不是一个非常灵活的选项。
答案4
使用 GNU sed(如果您还没有,请将其安装在您的 Mac 上):
$ sed 's/"[A-Z]"/\L&,"modifiers":"left_shift"/' file
{"key_code":"a"},
{"key_code":"b","modifiers":"left_shift"},
{"key_code":"c"},
{"key_code":"d","modifiers":"left_shift"}
\1
如果您使用而不是$1
反向引用并转义括号以使它们捕获组边界而不是文字,您现有的代码也可以在 GNU sed 中工作,例如:
$ sed 's/"\([A-Z]\)"/"\L\1","modifiers": "left_shift"/g' file
{"key_code":"a"},
{"key_code":"b","modifiers": "left_shift"},
{"key_code":"c"},
{"key_code":"d","modifiers": "left_shift"}
或者启用 ERE 而不是默认的 BRE:
$ sed -E 's/"([A-Z])"/"\L\1","modifiers": "left_shift"/g' file
{"key_code":"a"},
{"key_code":"b","modifiers": "left_shift"},
{"key_code":"c"},
{"key_code":"d","modifiers": "left_shift"}