标签 命令行 下的文章

这是一个非常有趣的脚本,每当用户在终端输入错误的命令时,它都会嘲讽用户。

它让你在解决一些问题时会感到快乐。有的人在受到终端嘲讽的时候感到不愉快。但是,当我受到终端的批评时,我真的很开心。

这是一个有趣的 CLI 工具,在你弄错的时候,会用随机短语嘲讽你。此外,它允许你添加自己的短语。

如何在 Linux 上安装 Bash-Insulter?

在安装 Bash-Insulter 之前,请确保你的系统上安装了 git。如果没有,请使用以下命令安装它。

对于 Fedora 系统, 请使用 DNF 命令 安装 git。

$ sudo dnf install git

对于 Debian/Ubuntu 系统,请使用 APT-GET 命令 或者 APT 命令 安装 git。

$ sudo apt install git

对于基于 Arch Linux 的系统,请使用 Pacman 命令 安装 git。

$ sudo pacman -S git

对于 RHEL/CentOS 系统,请使用 YUM 命令 安装 git。

$ sudo yum install git

对于 openSUSE Leap 系统,请使用 Zypper 命令 安装 git。

$ sudo zypper install git

我们可以通过 克隆 clone 开发人员的 GitHub 存储库轻松地安装它。

首先克隆 Bash-insulter 存储库。

$ git clone https://github.com/hkbakke/bash-insulter.git bash-insulter

将下载的文件移动到文件夹 /etc 下。

$ sudo cp bash-insulter/src/bash.command-not-found /etc/

将下面的代码添加到 /etc/bash.bashrc 文件中。

$ vi /etc/bash.bashrc

#Bash Insulter
if [ -f /etc/bash.command-not-found ]; then
 . /etc/bash.command-not-found
fi

运行以下命令使更改生效。

$ sudo source /etc/bash.bashrc

你想测试一下安装是否生效吗?你可以试试在终端上输入一些错误的命令,看看它如何嘲讽你。

$ unam -a

$ pin 2daygeek.com

如果你想附加你自己的短语,则导航到以下文件并更新它。你可以在 messages 部分中添加短语。

# vi /etc/bash.command-not-found

print_message () {

    local messages
    local message

    messages=(
        "Boooo!"
        "Don't you know anything?"
        "RTFM!"
        "Haha, n00b!"
        "Wow! That was impressively wrong!"
        "Pathetic"
        "The worst one today!"
        "n00b alert!"
        "Your application for reduced salary has been sent!"
        "lol"
        "u suk"
        "lol... plz"
        "plz uninstall"
        "And the Darwin Award goes to.... ${USER}!"
        "ERROR_INCOMPETENT_USER"
        "Incompetence is also a form of competence"
        "Bad."
        "Fake it till you make it!"
        "What is this...? Amateur hour!?"
        "Come on! You can do it!"
        "Nice try."
        "What if... you type an actual command the next time!"
        "What if I told you... it is possible to type valid commands."
        "Y u no speak computer???"
        "This is not Windows"
        "Perhaps you should leave the command line alone..."
        "Please step away from the keyboard!"
        "error code: 1D10T"
        "ACHTUNG! ALLES TURISTEN UND NONTEKNISCHEN LOOKENPEEPERS! DAS KOMPUTERMASCHINE IST NICHT FÜR DER GEFINGERPOKEN UND MITTENGRABEN! ODERWISE IST EASY TO SCHNAPPEN DER SPRINGENWERK, BLOWENFUSEN UND POPPENCORKEN MIT SPITZENSPARKEN. IST NICHT FÜR GEWERKEN BEI DUMMKOPFEN. DER RUBBERNECKEN SIGHTSEEREN KEEPEN DAS COTTONPICKEN HÄNDER IN DAS POCKETS MUSS. ZO RELAXEN UND WATSCHEN DER BLINKENLICHTEN."
        "Pro tip: type a valid command!"
        "Go outside."
        "This is not a search engine."
        "(╯°□°)╯︵ ┻━┻"
        "¯\_(ツ)_/¯"
        "So, I'm just going to go ahead and run rm -rf / for you."
        "Why are you so stupid?!"
        "Perhaps computers is not for you..."
        "Why are you doing this to me?!"
        "Don't you have anything better to do?!"
        "I am _seriously_ considering 'rm -rf /'-ing myself..."
        "This is why you get to see your children only once a month."
        "This is why nobody likes you."
        "Are you even trying?!"
        "Try using your brain the next time!"
        "My keyboard is not a touch screen!"
        "Commands, random gibberish, who cares!"
        "Typing incorrect commands, eh?"
        "Are you always this stupid or are you making a special effort today?!"
        "Dropped on your head as a baby, eh?"
        "Brains aren't everything. In your case they're nothing."
        "I don't know what makes you so stupid, but it really works."
        "You are not as bad as people say, you are much, much worse."
        "Two wrongs don't make a right, take your parents as an example."
        "You must have been born on a highway because that's where most accidents happen."
        "If what you don't know can't hurt you, you're invulnerable."
        "If ignorance is bliss, you must be the happiest person on earth."
        "You're proof that god has a sense of humor."
        "Keep trying, someday you'll do something intelligent!"
        "If shit was music, you'd be an orchestra."
        "How many times do I have to flush before you go away?"
    )

via: https://www.2daygeek.com/bash-insulter-insults-the-user-when-typing-wrong-command/

作者:Magesh Maruthamuthu 选题:lujun9972 译者:zero-mk 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这篇文章将了解一下 & 符号及它在 Linux 命令行中的各种用法。

如果阅读过我之前的三篇文章(123),你会觉得掌握连接各个命令之间的连接符号用法也是很重要的。实际上,命令的用法并不难,例如 mkdirtouchfind 也分别可以简单概括为“建立新目录”、“更新文件”和“在目录树中查找文件”而已。

但如果要理解

mkdir test_dir 2>/dev/null || touch images.txt && find . -iname "*jpg" > backup/dir/images.txt &

这一串命令的目的,以及为什么要这样写,就没有这么简单了。

关键之处就在于命令之间的连接符号。掌握了这些符号的用法,不仅可以让你更好理解整体的工作原理,还可以让你知道如何将不同的命令有效地结合起来,提高工作效率。

在这一篇文章和接下来的文章中,我会介绍如何使用 & 号和管道符号(|)在不同场景下的使用方法。

幕后工作

我来举一个简单的例子,看看如何使用 & 号将下面这个命令放到后台运行:

cp -R original/dir/ backup/dir/

这个命令的目的是将 original/dir/ 的内容递归地复制到 backup/dir/ 中。虽然看起来很简单,但是如果原目录里面的文件太大,在执行过程中终端就会一直被卡住。

所以,可以在命令的末尾加上一个 & 号,将这个任务放到后台去执行:

cp -R original/dir/ backup/dir/ &

任务被放到后台执行之后,就可以立即继续在同一个终端上工作了,甚至关闭终端也不影响这个任务的正常执行。需要注意的是,如果要求这个任务输出内容到标准输出中(例如 echols),即使使用了 &,也会等待这些输出任务在前台运行完毕。

当使用 & 将一个进程放置到后台运行的时候,Bash 会提示这个进程的进程 ID。在 Linux 系统中运行的每一个进程都有一个唯一的进程 ID,你可以使用进程 ID 来暂停、恢复或者终止对应的进程,因此进程 ID 是非常重要的。

这个时候,只要你还停留在启动进程的终端当中,就可以使用以下几个命令来对管理后台进程:

  • jobs 命令可以显示当前终端正在运行的进程,包括前台运行和后台运行的进程。它对每个正在执行中的进程任务分配了一个序号(这个序号不是进程 ID),可以使用这些序号来引用各个进程任务。
$ jobs
[1]- Running cp -i -R original/dir/* backup/dir/ &
[2]+ Running find . -iname "*jpg" > backup/dir/images.txt &
  • fg 命令可以将后台运行的进程任务放到前台运行,这样可以比较方便地进行交互。根据 jobs 命令提供的进程任务序号,再在前面加上 % 符号,就可以把相应的进程任务放到前台运行。
$ fg %1 # 将上面序号为 1 的 cp 任务放到前台运行
cp -i -R original/dir/* backup/dir/

如果这个进程任务是暂停状态,fg 命令会将它启动起来。

  • 使用 ctrl+z 组合键可以将前台运行的任务暂停,仅仅是暂停,而不是将任务终止。当使用 fg 或者 bg 命令将任务重新启动起来的时候,任务会从被暂停的位置开始执行。但 sleep 命令是一个特例,sleep 任务被暂停的时间会计算在 sleep 时间之内。因为 sleep 命令依据的是系统时钟的时间,而不是实际运行的时间。也就是说,如果运行了 sleep 30,然后将任务暂停 30 秒以上,那么任务恢复执行的时候会立即终止并退出。
  • bg 命令会将任务放置到后台执行,如果任务是暂停状态,也会被启动起来。
$ bg %1
[1]+ cp -i -R original/dir/* backup/dir/ &

如上所述,以上几个命令只能在同一个终端里才能使用。如果启动进程任务的终端被关闭了,或者切换到了另一个终端,以上几个命令就无法使用了。

如果要在另一个终端管理后台进程,就需要其它工具了。例如可以使用 kill 命令从另一个终端终止某个进程:

kill -s STOP <PID>

这里的 PID 就是使用 & 将进程放到后台时 Bash 显示的那个进程 ID。如果你当时没有把进程 ID 记录下来,也可以使用 ps 命令(代表 process)来获取所有正在运行的进程的进程 ID,就像这样:

ps | grep cp

执行以后会显示出包含 cp 字符串的所有进程,例如上面例子中的 cp 进程。同时还会显示出对应的进程 ID:

$ ps | grep cp
14444 pts/3 00:00:13 cp

在这个例子中,进程 ID 是 14444,因此可以使用以下命令来暂停这个后台进程:

kill -s STOP 14444

注意,这里的 STOP 等同于前面提到的 ctrl+z 组合键的效果,也就是仅仅把进程暂停掉。

如果想要把暂停了的进程启动起来,可以对进程发出 CONT 信号:

kill -s CONT 14444

这个给出一个可以向进程发出的常用信号列表。如果想要终止一个进程,可以发送 TERM 信号:

kill -s TERM 14444

如果进程不响应 TERM 信号并拒绝退出,还可以发送 KILL 信号强制终止进程:

kill -s KILL 14444

强制终止进程可能会有一定的风险,但如果遇到进程无节制消耗资源的情况,这样的信号还是能够派上用场的。

另外,如果你不确定进程 ID 是否正确,可以在 ps 命令中加上 x 参数:

$ ps x| grep cp
14444 pts/3 D 0:14 cp -i -R original/dir/Hols_2014.mp4
  original/dir/Hols_2015.mp4 original/dir/Hols_2016.mp4
  original/dir/Hols_2017.mp4 original/dir/Hols_2018.mp4 backup/dir/

这样就可以看到是不是你需要的进程 ID 了。

最后介绍一个将 psgrep 结合到一起的命令:

$ pgrep cp
8
18
19
26
33
40
47
54
61
72
88
96
136
339
6680
13735
14444

pgrep 可以直接将带有字符串 cp 的进程的进程 ID 显示出来。

可以加上一些参数让它的输出更清晰:

$ pgrep -lx cp
14444 cp

在这里,-l 参数会让 pgrep 将进程的名称显示出来,-x 参数则是让 pgrep 完全匹配 cp 这个命令。如果还想了解这个命令的更多细节,可以尝试运行 pgrep -ax

总结

在命令的末尾加上 & 可以让我们理解前台进程和后台进程的概念,以及如何管理这些进程。

在 UNIX/Linux 术语中,在后台运行的进程被称为 守护进程 daemon 。如果你曾经听说过这个词,那你现在应该知道它的意义了。

和其它符号一样,& 在命令行中还有很多别的用法。在下一篇文章中,我会更详细地介绍。


via: https://www.linux.com/blog/learn/2019/2/and-ampersand-and-linux

作者:Paul Brown 选题:lujun9972 译者:HankChow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我们的 Linux 命令行玩具日历的最后一天以一场盛大冒险结束。

今天是我们为期 24 天的 Linux 命令行玩具日历的最后一天。希望你一直有在看,但如果没有,请从头开始,继续努力。你会发现 Linux 终端有很多游戏、消遣和奇怪之处。

虽然你之前可能已经看过我们日历中的一些玩具,但我们希望对每个人而言至少有一件新东西。

今天的玩具是由 Opensource.com 管理员 Joshua Allen Holm 提出的:

“如果你的冒险日历的最后一天不是 ESR(Eric S. Raymond)的开源版的 Adventure 游戏 —— 它仍然使用经典的 advent 命令(在 BSD 游戏包中的 adventure) ,我会非常非常非常失望 ;-)“

这是结束我们这个系列的完美方式。

巨洞冒险 Colossal Cave Adventure (通常简称 Adventure),是一款来自 20 世纪 70 年代的基于文本的游戏,它引领产生了冒险游戏这个类型的游戏。尽管它很古老,但是当探索幻想世界时,Adventure 仍然是一种轻松消耗时间的方式,就像龙与地下城那样,地下城主可能会引导你穿过一个充满想象的地方。

与其带你了解 Adventure 的历史,我鼓励你去阅读 Joshua 的该游戏的历史这篇文章,以及为什么它几年前会重新复活,并且被重新移植。接着,克隆它的源码并按照安装说明在你的系统上使用 advent 启动游戏。或者,像 Joshua 提到的那样,可以从 bsd-games 包中获取该游戏的另一个版本,该软件包可能存在于你的发行版中的默认仓库。

你有喜欢的命令行玩具认为我们应该介绍么?今天我们的系列结束了,但我们仍然乐于在新的一年中介绍一些很酷的命令行玩具。请在下面的评论中告诉我,我会查看一下。让我知道你对今天玩具的看法。

一定要看看昨天的玩具,能从远程获得乐趣的 Linux 命令,明年再见!


via: https://opensource.com/article/18/12/linux-toy-adventure

作者:Jason Baker 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

何不在命令行中进行一次“烧烤”呢?

这里是《24 天了解 Linux 命令行小玩意》。如果你未曾读过本系列的文章,可以在本文的结尾部分获取上一篇文章的链接,以了解本系列的大概内容。我们所介绍的命令行小玩意可供你消遣无聊时光。

你或许知道它们其中的一些,也可能不曾知晓它们。无论如何,我们都希望你能度过一段愉快的时光。

如果你住在北半球的非热带地区,可能冬季来临时你会被冻得满脸通红。住在这里的我,最喜欢的事情便是在火炉旁惬意地边喝茶边读书。

不幸的是,我家刚好缺个放火炉的地方。不过,多亏了今天我要介绍的 aafire ,我仍然可以假装我坐在火炉旁。

在我所使用的系统里, aafire 被打包进了 aalib 。 aalib 是一个受人喜爱的库,它可以很方便地将图像转换成 ASCII 图并输出到终端(或其它任何地方)。 aalib 将多种多样的图像带入了 Linux 终端。你可以看看本系列的其它文章,了解一下其它小程序,以便配合使用并充分利用它们。在 Fedora 中,你可以通过以下命令来安装 aalib :

$ sudo dnf install aalib

接着,试着运行 aafire 命令。 aalib 默认会使用 GUI 模式,我们要进行一些操作来让它在终端中运行(毕竟这一系列文章都讲的是命令行)。十分幸运的是,仅需安装 curses) 就能实现我们想要的效果。请执行:

$ aafire -driver curses

如果你觉得 aalib 挺有意思,可以在 Sourceforge 上找到它的源码(以 LGPLv2 许可证开源)。

欢迎将你觉得有意思的命令行小程序投稿到原作者处,只需在原文下留言即可。

如果有兴趣,可以查看原作者的上一篇文章: 在命令行中步入黑客帝国


via: https://opensource.com/article/18/12/linux-toy-aafire

作者:Jason Baker 选题:lujun9972 译者:zhs852 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

本文将教你如何在 Linux 命令行终端中使用 boxes 工具绘制字符形状图形来包装你的文字让其更突出。

现在正值假期,每个 Linux 终端用户都该得到一点礼物。无论你是庆祝圣诞节还是庆祝其他节日,或者什么节日也没有,都没有关系。我将在接下来的几周内介绍 24 个 Linux 命令行小玩具,供你把玩或者与朋友分享。让我们享受乐趣,让这个月过得快乐一点,因为对于北半球来说,这个月有点冷并且沉闷。

对于我要讲述的内容,可能你之前就有些了解。但是,我还是希望我们都有机会学到一些新的东西(我做了一点研究,确保可以分享 24 个小玩具)。

24 个 Linux 终端小玩具中的第一个是叫做 boxes 的小程序。为何从 boxes 说起呢?因为在没有它的情况下很难将所有其他命令礼物包装起来!

在我的 Fedora 机器上,默认没有安装 boxes 程序,但它在我的普通仓库中可以获取到,所以用如下命令就可安装:

$ sudo dnf install boxes -y

如果你在使用其他 Linux 发行版,一般也都可以在默认仓库中找到 boxes

boxes 是我真正希望在高中和大学计算机课程中就使用的实用程序,因为善意的老师要求我在每个源文件、函数、代码块等开头添加一些特定外观的备注信息。

/***************/
/* Hello World */
/***************/

事实证明,一旦你需要在框内添加几行文字,并且格式化的将它们统一风格就会变得很乏味。而 boxes 是一个简单实用程序,它使用 ASCII 艺术风格的字符形状框来包围文本。其字符形状默认风格是源代码注释风格,但也提供了一些其他选项。

它真的很容易使用。使用管道,便可以将一个简短问候语塞进字符形状盒子里。

$ cat greeting.txt | boxes -d diamonds -a c

上面的命令输出结果如下:

       /\          /\          /\
    /\//\\/\    /\//\\/\    /\//\\/\
 /\//\\\///\\/\//\\\///\\/\//\\\///\\/\
//\\\//\/\\///\\\//\/\\///\\\//\/\\///\\
\\//\/                            \/\\//
 \/                                  \/
 /\      I'm wishing you all a       /\
//\\     joyous holiday season      //\\
\\//     and a Happy Gnu Year!      \\//
 \/                                  \/
 /\                                  /\
//\\/\                            /\//\\
\\///\\/\//\\\///\\/\//\\\///\\/\//\\\//
 \/\\///\\\//\/\\///\\\//\/\\///\\\//\/
    \/\\//\/    \/\\//\/    \/\\//\/
       \/          \/          \/

或者玩点更有趣的,比如:

echo "I am a dog" | boxes -d dog -a c

不要惊讶,它将会输出如下:

          __   _,--="=--,_   __
         /  \."    .-.    "./  \
        /  ,/  _   : :   _  \/` \
        \  `| /o\  :_:  /o\ |\__/
         `-'| :="~` _ `~"=: |
            \`     (_)     `/
     .-"-.   \      |      /   .-"-.
.---{     }--|  /,.-'-.,\  |--{     }---.
 )  (_)_)_)  \_/`~-===-~`\_/  (_(_(_)  (
(              I am a dog               )
 )                                     (
'---------------------------------------'

boxes 程序提供了很多选项 用于填充、定位甚至处理正则表达式。你可以在其 项目主页 上了解更多有关 boxes 的信息,或者转到 GitHub 去下载源代码或者贡献你自己的盒子形状。说到此,如果你想给你的提交找个好点子,我已经有了一个想法:为什么不能是一个节日礼物盒子?

         _  _
        /_\/_\
 _______\_\/_/_______
|       ///\\\       |
|      ///  \\\      |
|                    |
|     "Happy pull    |
|       request!"    |
|____________________|

boxes 是基于 GPLv2 许可证的开源项目。

你有特别喜欢的命令行小玩具需要我介绍的吗?这个系列要介绍的小玩具大部分已经落实,但还预留了几个空位置。如果你有特别想了解的可以评论留言,我会查看的。如果还有空位置,我会考虑介绍它的。即使要介绍的小玩具已经有 24 个了,但如果我得到了一些很好的意见,我会在最后做一些有价值的提及。

你可以通过 Drive a locomotive through your Linux terminal 来查看明天会介绍的命令行小玩具。


via: https://opensource.com/article/18/12/linux-toy-boxes

作者:Jason Baker 选题:lujun9972 译者:jrg 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

对于许多数据科学家来说,数据操作从始至终就是 Pandas 或 Tidyverse。从理论上讲,这样做没有任何问题。毕竟,这就是这些工具存在的原因。然而,对于像分隔符转换这样的简单任务,这些工具是大材小用了。

立志掌握命令行应该在每个开发人员的学习清单上,特别是数据科学家。学习 shell 的来龙去脉将无可否认地提高你的生产力。除此之外,命令行还是计算领域的一个重要历史课程。例如,awk —— 一种数据驱动的脚本语言。1977 年,在 Brain Kernighan(即传奇的 K&R 书中 K)的帮助下,awk 首次出现。今天,大约五十年过去了,awk 仍然活跃在每年新出版的书里面。因此,可以安全地假设对命令行魔法的付出不会很快贬值。

我们将涵盖什么

  • ICONV
  • HEAD
  • TR
  • WC
  • SPLIT
  • SORT & UNIQ
  • CUT
  • PASTE
  • JOIN
  • GREP
  • SED
  • AWK

ICONV

文件编码可能会很棘手。现在大部分文件都是 UTF-8 编码的。要了解 UTF-8 背后的一些魔力,请查看这个出色的视频。尽管如此,有时我们收到的文件不是这种编码。这可能引起对改变编码模式的一些胡乱尝试。这里,iconv 是一个拯救者。iconv 是一个简单的程序,它将获取采用一种编码的文本并输出采用另一种编码的文本。

# Converting -f (from) latin1 (ISO-8859-1)
# -t (to) standard UTF_8

iconv -f ISO-8859-1 -t UTF-8 < input.txt > output.txt

实用选项:

  • iconv -l 列出所有已知编码
  • iconv -c 默默丢弃无法转换的字符

HEAD

如果你是一个 Pandas 重度用户,那么会很熟悉 head。通常在处理新数据时,我们想做的第一件事就是了解其内容。这就得启动 Pandas,读取数据然后调用 df.head() —— 要说这有点费劲。没有任何选项的 head 将打印出文件的前 10 行。head 的真正力量在于干净利落的测试操作。例如,如果我们想将文件的分隔符从逗号更改为管道。一个快速测试将是:head mydata.csv | sed 's/,/|/g'

# Prints out first 10 lines
head filename.csv

# Print first 3 lines
head -n 3 filename.csv

实用选项:

  • head -n 打印特定行数
  • head -c 打印特定字节数

TR

tr 类似于翻译。这个功能强大的实用程序是文件基础清理的主力。理想的用例是替换文件中的分隔符。

# Converting a tab delimited file into commas
cat tab_delimited.txt | tr "\t" "," comma_delimited.csv

tr 另一个功能是你可以用内建 [:class:] 变量(POSIX 字符类)发挥威力。这些包括了:

  • [:alnum:] 所有字母和数字
  • [:alpha:] 所有字母
  • [:blank:] 所有水平空白
  • [:cntrl:] 所有控制字符
  • [:digit:] 所有数字
  • [:graph:] 所有可打印字符,但不包括空格
  • [:lower:] 所有小写字母
  • [:print:] 所有可打印字符,包括空格
  • [:punct:] 所有标点符号
  • [:space:] 所有水平或垂直空白
  • [:upper:] 所有大写字母
  • [:xdigit:] 所有 16 进制数字

你可以将这些连接在一起以组成强大的程序。以下是一个基本的字数统计程序,可用于检查 README 是否被滥用。

cat README.md | tr "[:punct:][:space:]" "\n" | tr "[:upper:]" "[:lower:]" | grep . | sort | uniq -c | sort -nr

另一个使用基本正则表达式的例子:

# Converting all upper case letters to lower case
cat filename.csv | tr '[A-Z]' '[a-z]'

实用选项:

  • tr -d 删除字符
  • tr -s 压缩字符
  • \b 退格
  • \f 换页
  • \v 垂直制表符
  • \NNN 八进制字符

WC

单词计数。它的价值主要来自其 -l 选项,它会给你提供行数。

# Will return number of lines in CSV
wc -l gigantic_comma.csv

这个工具可以方便地确认各种命令的输出。所以,如果我们在转换文件中的分隔符之后运行 wc -l,我们会期待总行数是一样的,如果不一致,我们就知道有地方出错了。

实用选项:

  • wc -c 打印字节数
  • wc -m 打印字符数
  • wc -L 打印最长行的长度
  • wc -w 打印单词数量

SPLIT

文件大小的范围可以很广。对于有的任务,拆分文件或许是有好处的,所以使用 split 吧。split 的基本语法是:

# We will split our CSV into new_filename every 500 lines
split -l 500 filename.csv new_filename_
# filename.csv
# ls output
# new_filename_aaa
# new_filename_aab
# new_filename_aa

它有两个奇怪的地方是命名约定和缺少文件扩展名。后缀约定可以通过 -d 标志变为数字。要添加文件扩展名,你需要运行以下 find 命令。它将通过附加 .csv 扩展名来更改当前目录中所有文件的名称,所以小心了。

find . -type f -exec mv '{}' '{}'.csv \;
# ls output
# filename.csv.csv
# new_filename_aaa.csv
# new_filename_aab.csv
# new_filename_aac.csv

实用选项:

  • split -b N 按特定字节大小分割
  • split -a N 生成长度为 N 的后缀
  • split -x 使用十六进制后缀

SORT & UNIQ

上面两个命令很明显:它们的作用就是字面意思。这两者结合起来可以提供最强大的冲击 (例如,唯一单词的数量)。这是由于 uniq 只作用于重复的相邻行。这也是在输出前进行 sort 的原因。一个有趣的事情是 sort -u 会达到和典型的 sort file.txt | uniq 模式一样的结果。

sort 对数据科学家来说确实具有潜在的有用能力:能够根据特定列对整个 CSV 进行排序。

# Sorting a CSV file by the second column alphabetically
sort -t"," -k2,2 filename.csv

# Numerically
sort -t"," -k2n,2 filename.csv

# Reverse order
sort -t"," -k2nr,2 filename.csv

这里的 -t 选项将逗号指定为分隔符,通常假设分隔符是空格或制表符。此外,-k 选项是为了确定我们的键。这里的语法是 -km,nm 作为开始列,n 作为结束列。

实用选项:

  • sort -f 忽略大小写
  • sort -r 反向排序
  • sort -R 乱序
  • uniq -c 统计出现次数
  • uniq -d 只打印重复行

CUT

cut 用于删除列。作为演示,如果我们只想删除第一和第三列。

cut -d, -f 1,3 filename.csv

要选择除了第一行外的所有行。

cut -d, -f 2- filename.csv

结合其他命令,将 cut 用作过滤器。

# Print first 10 lines of column 1 and 3, where "some_string_value" is present
head filename.csv | grep "some_string_value" | cut -d, -f 1,3

查出第二列中唯一值的数量。

cat filename.csv | cut -d, -f 2 | sort | uniq | wc -l

# Count occurences of unique values, limiting to first 10 results
cat filename.csv | cut -d, -f 2 | sort | uniq -c | head

PASTE

paste 是一个带有趣味性功能的特定命令。如果你有两个需要合并的文件,并且它们已经排序好了,paste 帮你解决了接下来的步骤。

# names.txt
adam
john
zach

# jobs.txt
lawyer
youtuber
developer

# Join the two into a CSV
paste -d ',' names.txt jobs.txt > person_data.txt

# Output
adam,lawyer
john,youtuber
zach,developer

更多 SQL 式变种,见下文。

JOIN

join 是一个简单的、 准切向的 quasi-tangential SQL。最大的区别是 join 将返回所有列以及只能在一个字段上匹配。默认情况下,join 将尝试使用第一列作为匹配键。为了获得不同结果,必须使用以下语法:

# Join the first file (-1) by the second column
# and the second file (-2) by the first
join -t "," -1 2 -2 1 first_file.txt second_file.txt

标准的 join 是内连接。然而,外连接通过 -a 选项也是可行的。另一个值得一提的技巧是 -q 标志,如果发现有缺失的字段,可用于替换值。

# Outer join, replace blanks with NULL in columns 1 and 2
# -o which fields to substitute - 0 is key, 1.1 is first column, etc...
join -t"," -1 2 -a 1 -a2 -e ' NULL' -o '0,1.1,2.2' first_file.txt second_file.txt

它不是最用户友好的命令,而是绝望时刻的绝望措施。

实用选项:

  • join -a 打印不可配对的行
  • join -e 替换丢失的输入字段
  • join -j 相当于 -1 FIELD -2 FIELD

GREP

grep 用正则表达式全局搜索并且打印 Global search for a Regular Expression and Print ,可能是最有名的命令,并且名副其实。grep 很强大,特别适合在大型代码库中查找。在数据科学的王国里,它充当其他命令的提炼机制。虽然它的标准用途也很有价值。

# Recursively search and list all files in directory containing 'word'

grep -lr 'word' .

# List number of files containing word

grep -lr 'word' . | wc -l

计算包含单词或模式的总行数。

grep -c 'some_value' filename.csv

# Same thing, but in all files in current directory by file name

grep -c 'some_value' *

对多个值使用“或”运算符: \|

grep "first_value\|second_value" filename.csv

实用选项:

  • alias grep="grep --color=auto" 使 grep 色彩丰富
  • grep -E 使用扩展正则表达式
  • grep -w 只匹配整个单词
  • grep -l 打印匹配的文件名
  • grep -v 非匹配

大人物们

sedawk 是本文中最强大的两个命令。为简洁起见,我不打算详细讨论这两个命令。相反,我将介绍各种能证明其令人印象深刻的力量的命令。如果你想了解更多,这儿就有一本书是关于它们的。

SED

sed 本质上是一个流编辑器。它擅长替换,但也可以用于所有输出重构。

最基本的 sed 命令由 s/old/new/g 组成。它的意思是搜索 old,全局替换为 new。 如果没有 /g,我们的命令将在 old 第一次出现后终止。

为了快速了解它的功能,我们可以深入了解一个例子。 在以下情景中,你已有以下文件:

balance,name
$1,000,john
$2,000,jack

我们可能想要做的第一件事是删除美元符号。-i 标志表示原位。'' 表示零长度文件扩展名,从而覆盖我们的初始文件。理想情况下,你可以单独测试,然后输出到新文件。

sed -i '' 's/\$//g' data.txt
# balance,name
# 1,000,john
# 2,000,jack

接下来,去除 blance 列的逗号。

sed -i '' 's/\([0-9]\),\([0-9]\)/\1\2/g' data.txt
# balance,name
# 1000,john
# 2000,jack

最后 jack 有一天决定辞职。所以,再见了,我的朋友。

sed -i '' '/jack/d' data.txt
# balance,name
# 1000,john

正如你所看到的,sed 有很多强大的功能,但乐趣并不止于此。

AWK

最好的留在最后。awk 不仅仅是一个简单的命令:它是一个成熟的语言。在本文中涉及的所有内容中,awk 是目前为止最酷的。如果你感兴趣,这里有很多很棒的资源 —— 看 这里这里这里

awk 的常见用例包括:

  • 文字处理
  • 格式化文本报告
  • 执行算术运算
  • 执行字符串操作

awk 可以以最原生的形式并行 grep

awk '/word/' filename.csv

或者更加神奇:将 grepcut 组合起来。在这里,对于所有带我们指定单词 word 的行,awk 打印第三和第四列,用 tab 分隔。-F, 用于指定切分时的列分隔符为逗号。

awk -F, '/word/ { print $3 "\t" $4 }' filename.csv

awk 内置了许多精巧的变量。比如,NF —— 字段数,和 NR —— 记录数。要获取文件中的第 53 条记录:

awk -F, 'NR == 53' filename.csv

更多的花招是其基于一个或多个值进行过滤的能力。下面的第一个示例将打印第一列等于给定字符串的行的行号和列。

awk -F, ' $1 == "string" { print NR, $0 } ' filename.csv

# Filter based off of numerical value in second column
awk -F, ' $2 == 1000 { print NR, $0 } ' filename.csv

多个数值表达式:

# Print line number and columns where column three greater
# than 2005 and column five less than one thousand

awk -F, ' $3 >= 2005 && $5 <= 1000 { print NR, $0 } ' filename.csv

求出第三列的总和:

awk -F, '{ x+=$3 } END { print x }' filename.csv

在第一列等于 something 的那些行,求出第三列值的总和。

awk -F, '$1 == "something" { x+=$3 } END { print x }' filename.csv

获取文件的行列数:

awk -F, 'END { print NF, NR }' filename.csv

# Prettier version
awk -F, 'BEGIN { print "COLUMNS", "ROWS" }; END { print NF, NR }' filename.csv

打印出现了两次的行:

awk -F, '++seen[$0] == 2' filename.csv

删除重复的行:

# Consecutive lines
awk 'a !~ $0; {a=$0}']

# Nonconsecutive lines
awk '! a[$0]++' filename.csv

# More efficient
awk '!($0 in a) {a[$0];print}

使用内置函数 gsub() 替换多个值。

awk '{gsub(/scarlet|ruby|puce/, "red"); print}'

这个 awk 命令将组合多个 CSV 文件,忽略标题,然后在最后附加它。

awk 'FNR==1 && NR!=1{next;}{print}' *.csv > final_file.csv

需要缩小一个庞大的文件? awk 可以在 sed 的帮助下处理它。具体来说,该命令根据行数将一个大文件分成多个较小的文件。这个一行脚本将增加一个扩展名。

sed '1d;$d' filename.csv | awk 'NR%NUMBER_OF_LINES==1{x="filename-"++i".csv";}{print > x}'

# Example: splitting big_data.csv into data_(n).csv every 100,000 lines
sed '1d;$d' big_data.csv | awk 'NR%100000==1{x="data_"++i".csv";}{print > x}'

结语

命令行拥有无穷无尽的力量。本文中介绍的命令足以将你从一无所知提升到英雄人物。除了涵盖的内容之外,还有许多实用程序可以考虑用于日常数据操作。Csvkitxsv 还有 q 是需要记住的三个。如果你希望更深入地了解命令行数据科学,查看这本书。它也可以免费在线获得!


via: http://kadekillary.work/post/cli-4-ds/

作者:Kade Killary 选题:lujun9972 译者:GraveAccent 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出