首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

@程序员,你真的会用 Unix 命令?

  • 24-03-05 01:01
  • 3394
  • 6257
blog.csdn.net

640?wx_fmt=gif

 

那些常用的 Unix 命令,你不知道的功能!

640?wx_fmt=jpeg

 

作者 | Vegard Stikbakke 

译者 | 弯月

责编 | 屠敏

出品 | CSDN(ID:CSDNNews)

如何挑战百万年薪的人工智能!

https://edu.csdn.net/topic/ai30?utm_source=csdn_bw

以下为译文:

我逐渐意识到,Unix 的命令行工具可以解决一切与文字处理有关的问题。我来讲一个我遇到过的问题,以及怎样用 Unix 命令行工具解决的。

 

640?wx_fmt=png

问题

 

我在做我的硕士论文研究。像许多统计学家一样,我需要进行许多模拟。首先我利用一些数字的种子(以保证可复现性)来模拟了一些数据,然后在这些数据上用一个算法来估算一些东西。每次运行模拟时我都会创建一些文件,大概像下面这样:

  1. dataset-directory/0001_data.csv
  2. dataset-directory/0001_A.csv

但有时候运行会失败。这并不是太严重,模拟失败了我只需要运行另一个模拟就好了。比如,0001 这个数据我成功地运行了算法 A。因此我想在 0001 数据上使用算法 B。但我真正需要的是跟踪哪些命令失败了。

在许多数据上运行算法 A 之后,我得到了一大堆文件,像这样:

  1. dataset-directory/0001_data.csv
  2. dataset-directory/0001_A.csv
  3. dataset-directory/0002_data.csv
  4. dataset-directory/0002_A.csv
  5. dataset-directory/0003_data.csv
  6. dataset-directory/0003_A.csv
  7. dataset-directory/0004_data.csv
  8. dataset-directory/0005_data.csv
  9. dataset-directory/0005_A.csv
  10. dataset-directory/0006_data.csv
  11. dataset-directory/0006_A.csv
  12. dataset-directory/0007_data.csv
  13. dataset-directory/0007_A.csv
  14. dataset-directory/0008_data.csv
  15. dataset-directory/0009_data.csv
  16. dataset-directory/0009_A.csv
  17. ...
  18. dataset-directory/0499_A.csv

通过观察得知算法 A 在数据 0004 和 0008 上的结果不存在。那么,怎样才能列出所有 A 没有成功的数据呢?

我当然可以手工来做,但那样很容易出错,而且很麻烦。要是能写程序完成就最好了!

 

640?wx_fmt=png

解决方案

 

简单地来说,那些没有成功的就是从0001到0500的数字中去掉那些成功了的数字。而得到数字列表的最好命令就是 seq:

  1. $> seq 10
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. 10

(如果只给出一个数字,那么默认序列从1开始。当然,seq 2 10也会按照你期待的那样工作。)

现在,如果我能获得成功运行的列表,就可以通过 seq 命令生成所有可能的数字,再交叉检查两个列表来获得想要的结果了!

许多命令行工具只完成一项工作。例如,cut 可以获得每行指定位置上的字符:

  1. $> cat text
  2. Lorem ipsum
  3. dolor sit amet
  4. $> cat text | cut -c 2-5
  5. orem
  6. olor

注意这里使用了所谓的“管道运算符” | 。我说过,许多工具只做一件事,而且把那件事做到最好。很方便的是这些工具可以组合使用。使用管道,左边命令的结果就会变成右边命令的输入。注意这些命令会将输入当做一系列行来处理,通常来说这非常方便。

我们可以把成功的文件名单列表利用管道输入至 grep 命令,该命令可以使用正则表达式来查找。由于所有文件都以同样长度的四个数字开始,我们可以利用正则表达式 \d\d\d\d 来匹配这四个连续的数字,然后将文件末尾的 A 算法加到正则表达式中。要获得文件列表,每行一个文件,只需执行 ls。(尽管直接调用 ls 时并不会显示成每行一个文件,但放在管道中时输出就会变成这样。)

  1. $> ls dataset-directory | grep '\d\d\d\d_A.csv'
  2. 0009_A.csv
  3. 0001_A.csv
  4. 0002_A.csv
  5. 0005_A.csv
  6. 0007_A.csv
  7. 0003_A.csv
  8. 0006_A.csv
  9. ...

出于某些原因,在使用 grep 之后这里的顺序混乱了。我们可以使用 sort 命令来改正。而且由于我们只关心数字,可以使用 cut -c 1-4 来取出数字部分。

  1. $> ls dataset-directory | grep '\d\d\d\d_A.csv' | sort | cut -c 1-4
  2. 0001
  3. 0002
  4. 0003
  5. 0005
  6. 0006
  7. 0007
  8. 0009
  9. ...
  10. 0499

这些数字跟 seq 命令的结果不太一样,因为它们前面补了零。我们可以使用一段 Python 脚本将它们转成整数。

  1. # parse.py
  2. import sys
  3. for line in sys.stdin:
  4.     i = int(line)
  5.     print(i)

现在将结果用管道导入这个脚本就能得到我们需要的数字:

  1. $> ls dataset-directory | grep '\d\d\d\d_A.csv' | cut -c 1-4 | python3 parse.py
  2. 1
  3. 2
  4. 3
  5. 5
  6. 6
  7. 7
  8. 9
  9. ...
  10. 499

接近目标了!现在需要找出怎样才能交叉检查这两个数字的列表。幸运的是,有个命令叫做comm,它能检查两个输入流中的公共字符。为了将上面这个命令的输出作为输入使用,我们可以将其求值后重定向,只需使用<(...)即可实现:

  1. $> comm <(ls dataset-directory | grep '\d\d\d\d_A.csv' | cut -c 1-4 | python3 parse.py) <(seq 500)
  2.         1
  3.         2
  4.         3
  5.     4
  6.         5
  7.         6
  8.         7
  9.     8
  10.         9
  11.     10
  12. ...
  13.     500

这个输出不是太好理解。阅读 comm 的手册(运行 man comm)可以发现,comm 会“产生三列的输出,分别是:只存在于 file1 的行,只存在于 file2 的行,以及存在于两个文件的行”。要去掉第一列(其实它是空的,因为没有任何数字只存在于文件列表中),可以在调用 comm 时加入参数-1。我们也不关心同时存在于两个输入中的数字,因此还要传递标志-3。

  1. $> comm -1 -3 <(ls dataset-directory | grep '\d\d\d\d_A.csv' | cut -c 1-4 | python3 parse.py) <(seq 500)
  2. 4
  3. 8
  4. ...
  5. 500

搞定!

 

640?wx_fmt=png

网友说

 

这个方法发布之后,在 Hacker News(https://news.ycombinator.com/item?id=19160659)上引发无数网友参与讨论:

评论 1:

Unix CLI 工具最有意思的地方在于有数百万种有效的方法来解决问题。我还想到了我自己的“更好”的解决方案,跟这里说过的大多数方法完全不同的方法。但这不是重点。

这篇文章的优点在于它遵循逐步解决问题的过程。我发现很多与我一起工作的程序员都在努力解决 CLI 问题,我觉得这有点令人惊讶。但我认为这完全取决于你如何看待这样的问题。

如果你从“我如何构建一个函数来操作这个原始数据?”或“哪种数据结构最能表达这些文件名之间的关系?”那么肯定会遇到困难。但是,如果你考虑“如何改变这些数据以消除无关的细节?”和“我有什么工具可以解决数据上的问题,如果有一些麻烦,我怎么能解决这些麻烦?”并且如果能接受采用逐步的方式,而不是构建和操纵整个抽象逻辑结构,那么你就可以有效地利用这些工具在几分钟之内解决这些问题,无需花费几小时。

评论 2:

这篇文章的问题是:“cut”命令后的参数并没有什么标准格式。

更糟糕的是,看似有标准格式,其实被许多其他格式破坏了。通常,这些格式取决于最初的作者,以及当时人们流行的想法。所以,有时候标志会“聚集”在一起,同时假设多字符的标志会使用两个横线作为开始。后来一些程序开始用一个横线来表示多字符的标志。还有许多其他的不一致。如果我学习了cut的基本范围语法,我能知道 imagemagick 的基本语法吗?

这些不一致在技术上并不冲突,因为每个只存在于特定的背景下。但是,如果看到那些不一致的东西被放在管道两侧,特别是当其中一个是非标准用法时,理智上真的很痛苦。 (或者,即使它只是你需要的一个命令,但是你使用了错误的标志语法。)这一切都增加了认知负荷。

哦,从 Bash 转到 Python 语言是一个巨大的风险。如果你每天使用 Python 编写脚本,那可能还问题不大。但对于读者来说,语言边界是巨大的。因为用户不仅需要处理运行时错误和格式错误,而且还需要处理语言错误。如果命令行跳出一个语法错误或异常,我相信大多数读者就不会再读下去了。

程序员转行学什么语言?

https://edu.csdn.net/topic/ai30?utm_source=csdn_bw

 

原文:http://vegardstikbakke.com/unix/

本文为 CSDN 翻译,如需转载,请注明来源出处。

【End】

640?wx_fmt=jpeg

 热 文 推 荐 

谁杀死了芯片?

PPT写得好的人,为什么都如此遭人痛恨?

王思聪也救不了熊猫直播了?

程序员撒狗粮!3 天开发自己的婚礼小程序!

300道Python面试题,备战春招!

☞ 5年Go语言经验薪资翻倍! 这份全球职业报告中, 区块链开发者薪资排第三, 前两名你绝对想不到!(含完整版下载资源)

☞ 女神节 |  那些奋斗在IT领域的“女神”们

☞ 没有一个人,能躲过程序员的诱惑!

 

System.out.println("点个好看吧!");
console.log("点个好看吧!");
print("点个好看吧!");
printf("点个好看吧!\n");
cout << "点个好看吧!" << endl;
Console.WriteLine("点个好看吧!");
Response.Write("点个好看吧!");
alert("点个好看吧!")
echo "点个好看吧!"

640?wx_fmt=gif点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。

640?wx_fmt=png喜欢就点击“好看”吧!

CSDN
微信公众号
成就一亿技术人
注:本文转载自blog.csdn.net的CSDN资讯的文章"https://blog.csdn.net/csdnnews/article/details/88386547"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top