这个搞法很靠谱,基于 awk或sed + sort实现
1 需要排序的markdown文件
- 对文件第三列进行排序
cat my_list.md
#| **服务名** | **优先级** |
#| ---------------- | -------- |
| neo4j-srv | 0 |
| gc-gaway |20 |
| gc-gaway |2 |
| redis-srv |0 |
| gc-gateway | 10 |
2 基于awk的实现
- 语法实现:
for i in `awk -F '|' '{split($3,a," ");print NR,a[1]a[2]}' my_list.md | sort -n -k 2 | awk '{print $1}'`;
do
#awk 'NR=='$i'{print}' my_list.md
awk "NR=="$i'{print}' my_list.md #--- 同上面一样,用两个不一样的引号,好理解些
done
- 语法原理:
1. awk -F '|' '{split($3,a," ");print NR,a[1]a[2]}' my_list.md | sort -n -k 2 | awk '{print $1}'
使用【'|'】 作为字段分隔符,用split对第三个字段【$3】进行二次分割,二次分隔符是空格【" "】,二次分割结果保存到数组【a】里,然后打印当前行号【NR】及数组的所有的值【a[1]a[2]】(特别说明:这里是为了去掉第三个字段里面的空格然后用于排序,这里一般打印【a[1]】就够了,字段中间不会有空格);
2. 然后在对【a[1]a[2]】的组合体按数字大小进行排序【-n】,【a[1]a[2]】是输出的第二列(第一列是行号【NR】),所以【-k 2】;
3. 然后打印当前第一列的值【$1】,即行号【NR】,这是按第三个字段【$3】排过序的行号顺序
4. for循环得到行号列表,然后按行号顺序输出原文件行内容,完美
3 基于sed的实现
- 语法实现
sed -E 's/(^\|[ ]*[a-zA-Z0-9 _-]+\|)[ ]*([0-9]+)[ ]*(\|)[ ]*$/\1\2\3/' my_list.md | sort -t '|' -n -k 3
- 语法原理:
用正则分成几段匹配,然后取出自己想要的(这样是为了删除排序列的空格,以便于排序)
A、 匹配列:
(^\|[ ]*[a-zA-Z0-9 _-]+\|)[ ]*([0-9]+)[ ]*(\|)[ ]*$ :
1. (^\|[ ]*[a-zA-Z0-9 _-]+\|) :第一段是倒数第二个【|】前面的(包含),要留下\1
2. [ ]* : 要排序那一列的前导空格,这个是要丢弃的
3. ([0-9]+) : 要排序那一列的数值,用它排序,要留下\2
4. [ ]* : 要排序那一列的后导空格,这个是要丢弃的
5. (\|) : 要排序那一列的分隔符,要留下\3
6. [ ]*$ : 后面的空格,丢弃
B、替换列:
\1\2\3
C、排序
sort -t '|' -n -k 3
-t '|' : 分隔符【|】
-n : 作为数值类型排序
-k 3 : 用第三列排序
4 后话
一般情况,如果文档很工整,比如字段前面没有空格,我们用sort就可以很好的完成排序了(这种情况很少)。如果字段前面有空格,就会会影响排序结果。如果你不介意删除文档中的空格的话,也可以使用sed删除所有空格(sed -i ‘s/\s//g’ filename),然后用sort快速实现排序(sort -t ‘|’ -n -k 3)。但很多时候我们并不希望删除文档中的空格(例如:排版需要或参数文件必须),这时就只能按上面的思路来搞了。
上面用awk实现的好处是完全不会修改原文件,而sed会修改需要排序的那一列
爱你!