第2章:Shell高级技巧

[TOC]

Shell高级技巧

1
2
3
4
5
# [shell替换和去掉换行符](http://www.noobyard.com/article/p-ahlemikj-nz.html)
featureBranceNamesString=$(echo ${featureBranceNamesString} |sed 's/ /\n/g'|awk '{{printf"%s",$0}}')

# [Shell 命令变量去除空格方法](https://blog.csdn.net/jjc120074203/article/details/126663391)
FileContent=${FileContent// /}

其他问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# [Mac环境下shell脚本中的map](https://www.jianshu.com/p/a55480b793b0)
# declare -A myMap=(["my00"]="00" ["my01"]="01")
# myMap["my02"]="02"
# myMap["my03"]="03"
# declare -A targetBranchConfig_realMap=()
# targetBranchConfig_realMap["uploadChannelShortcut"]="${packagePgyerChannelShortcutResult_upload}"
# targetBranchConfig_realMap["uploadChannelKey"]="${packagePgyerChannelKeyResult_upload}"

uploadChannelShortcut_key="uploadChannelShortcut"
uploadChannelKey_key="uploadChannelKey"
targetBranchConfig_realMap="{"
targetBranchConfig_realMap+="\"${uploadChannelShortcut_key}\":\"${packagePgyerChannelShortcutResult_upload}\", \"${uploadChannelKey_key}\":\"${packagePgyerChannelKeyResult_upload}\""
if [ -z "${packagePgyerChannelShortcutResult_download}" ] || [ "${packagePgyerChannelShortcutResult_download}" == "null" ]; then
packagePgyerChannelShortcutResult_download=${packagePgyerChannelShortcutResult_upload}
packagePgyerChannelKeyResult_download=${packagePgyerChannelKeyResult_upload}
fi
targetBranchConfig_realMap+=","
targetBranchConfig_realMap+="\"downloadChannelShortcut\":\"${packagePgyerChannelShortcutResult_download}\", \"downloadChannelKey\":\"${packagePgyerChannelKeyResult_download}\""
targetBranchConfig_realMap+="}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#获取键值对的个数,或者数组长度:
cat json.txt | jq '.[0].employees|length'

# 取键foo的值:
echo '{"foo": 42, "bar": "less interesting data"}' | jq '.foo'
42
# 获取json所有键:
echo '{"foo": 42, "bar": "less interesting data"}' | jq 'keys'
[
"bar",
"foo"
]
# has判断是否存在某个key
echo '{"foo": 42, "bar": "less interesting data"}' | jq 'has("foo")'
true
# 获取键值对的个数,或者数组长度
echo '{"foo": 42, "bar": "less interesting data"}' | jq 'length'

一、主要用法

删除所有的空格

1
2
3
4
buildContainBranchsString=(`echo ${buildContainBranchsString} | sed s/[[:space:]]//g`) # 删除所有的空格,修复所填分支信息有空格

#echo "buildContainBranchsString=${buildContainBranchsString}"
buildContainBranchArray=(`echo ${buildContainBranchsString} | tr '#' ' '`) # 字符串拆分成数组

字符串转换数组

1
2
3
4
nocodeBranceNamesString=$(cat ${FILE_PATH} | ${JQ_EXEC} '.nocode_brances' | ${JQ_EXEC} '.[].name')
echo ${nocodeBranceNamesString}

nocodeBranceNamesArray=(${nocodeBranceNamesString//,/}) # 字符串转数组

shell 使用jq解析json字符串数组

如何在shell中使用jq cmd变量

1
2
3
#    branchMapArray=$(echo ${branchRootMap} | ${JQ_EXEC} -r '.online_brances') # -r 去除字符串引号
# [如何在shell中使用jq cmd变量](https://www.5axxw.com/questions/content/5ucfc4)
branchMapArray=$(echo ${branchRootMap} | jq -r --arg branchsKey "$branchsKey" '.[$branchsKey]')
1
brew install shc
1
2
3
shc -r -f hello_script.sh

shc -r -f hello_script.sh -o hello_script
1
2
3
4
5
6
7
8
9
10
11
12
shell 单括号运算符号:
a=$(date);
等同于:
a=date;



双括号运算符:
a=$((1+2));
echo $a;
等同于:
a=expr 1 + 2

删除

1
2
3
4
5
6
7
8
#删除所有的空格
sed s/[[:space:]]//g

#删除行末空格
sed 's/[ \t]*$//g'

#删除行首空格
sed 's/^[ \t]*//g'

shell中使用jq命令修改json文件(合并,修改等)

  1. 目标

文件package.json

1
2
3
4
5
6
7
8
9
10
{
"menus": {
"commandPalette": [
{
"command": "go.test.refresh",
"when": "false"
}
]
}
}

文件add.json

1
2
3
4
5
6
7
8
9
10
11
12
{
"add_menu": [
{
"command": "go.explorer.refresh",
"when": "false"
},
{
"command": "go.explorer.open",
"when": "false"
}
]
}

希望把add.json文件里的add_menu合并到package.json的 menus.commandPalette中, 得到一下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"menus": {
"commandPalette": [
{
"command": "go.test.refresh",
"when": "false"
},
{
"command": "go.explorer.refresh",
"when": "false"
},
{
"command": "go.explorer.open",
"when": "false"
}
]
}
}

2.上脚本

1
jq -s '.[0].menus.commandPalette = .[0].menus.commandPalette + .[1].add_menu | .[0]' ./package.json ./add.json

3.解释

参数-s

表示读取多个json对象, 放入一个数组里在一起出来, 开始的.表示整个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ jq -s '.' ./package.json ./add.json
[
{
"menus": {
"commandPalette": [
...
]
}
},
{
"add_menu": [
...
]
}
]

定位取值

数组使用中括号加索引读取等读取, 如 [0] [1], 原命令里的.[0]和.[1]就分别是表示package.json和info.json里的json对象, 其中的.则是表示合并后数组.

要获取json更深层级的对象时, key之间用点号拼接即可. 如

1
2
$ jq '.add_menu[0].command' ./add.json 
"go.explorer.refresh"

管道|

基本和shell里的管道概念是一致的, 管道左侧命令的输出, 将变成管道右侧命令的输入. 如原命令里, .[0].menus.commandPalette = .[0].menus.commandPalette + .[1].add_menu | .[0] 就有一个管道, 左侧的命令是修改合并后的数组中第一个单元的某些值, 然后输出整个数组(包含两个单元, 有package.json和info.json的信息), 然后管道右侧命令接收到整个数组后, 只筛选出第一个单元进行输出

加法

  • 针对数组, 是拼接效果(如原命令)
  • 针对数字, 则是正常加法
  • 针对{}对象, 合并, 相同key覆盖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 数组加法
$ echo '[1,2] [3,4]'|jq -s '.[0] + .[1]'
[
1,
2,
3,
4
]

# 数字加法
$ echo '1 2'|jq -s '.[0] + .[1]'
3

# {}对象, 相同key后面覆盖前面
$ echo '{"a":1, "b":2} {"b":21, "c":3}'|jq -s '.[0] + .[1]'
{
"a": 1,
"b": 21,
"c": 3
}

4.总结

从某个数据源读取一些json信息, 并以此针对某个json的制定位置进行修改, 基本思路就是使用-s参数, 先把所有数据合并为一个大数组, 然后就行修改, 过后通过管道筛选出需要的数据.

jq是一个非常强悍的处理json的命令行工具, 完全可以把它当做一门语言来学. 我也正在学习当中, 你若有jq相关需求解决不了, 我很乐意帮忙研究解决.

二、超时

MacOS超时指令-gtimeout

在linux下面可以使用timeout命令设置命令的超时时间,macos下同样也有,只不过不是timeout而是gtimeout命令

安装

1
brew install coreutils

使用

1
gtimeout 10 sh ./demo.sh # 指令脚本,10秒后超时退出

也可以使用别名,将gtimeout设置为timeout

1
alias timeout=gtimeout