【问题标题】:How to make $1 a variable and get the first character? [duplicate]如何使 $1 成为变量并获取第一个字符? [复制]
【发布时间】:2020-04-17 19:47:21
【问题描述】:

我正在尝试自定义终端命令。我刚刚了解到我应该使用 Unix 脚本来做这件事?我真的不知道那是什么,我仍在努力弄清楚。我所知道的是 $1 是一个 arg 是否可以将其设为变量,然后像在 python 中一样获取第一个字母?

前:

str = 'happy'
str[0] = 'h'

【问题讨论】:

  • 您的 Python 示例引发了 TypeError: 'str' object does not support item assignmentstr 也是一个错误的变量名,但这不是重点。
  • $1 一个变量(也是一个参数FWIW)。你的意思是你想给它一个名字?如果是这样,那就是name="$1",你真的应该做一个shell教程。
  • $1第一个位置参数(例如第一个命令行参数)。要获取 bash 中的第一个字符,只需 ${1:0:1}(例如 ${var:offset_from_beg:nchars}
  • @wjandrea 我不认为他的意思是作为一个任务,他只是说str[0] 的值等于'h'

标签: bash shell unix


【解决方案1】:

你在这里问了几个不同的问题。

我正在尝试自定义终端命令。

这可能意味着一些不同的东西,但最明显的意思是你想在你的 path 中添加一个可执行文件,这样当你在终端输入它时,它就像您系统上的任何其他可执行文件一样运行。这只需要几件事:

  1. 必须设置可执行权限。
  2. 文件必须指定如何执行。对于 bash 脚本或 python 脚本等解释程序,您可以通过指定文件解释器的“shebang 行”开始文件。
  3. 该文件必须位于您的$PATH 指定的位置之一。

我刚刚得知我应该使用 Unix 脚本来做这件事?

没有“unix 脚本”之类的东西,但您似乎指的是“shell 脚本”。尽管这些通常与 unix 相关联,但它们本质上并不比任何其他语言都更本质上是 unix 脚本。 shell,例如bashsh 或任何其他的,只是一种解释性语言,其设计目的是方便人类交互使用以及作为保存文件的一部分以编程方式执行。

我不太了解那是什么,我仍在努力弄明白。

让我们进入一些细节。

首先我编辑一个名为“hello-world”的文件以包含:

#!/bin/bash
echo "Hello, world!"

请注意,此文件名没有“扩展名”。尽管有时使用基于文件扩展名的启发式方法(尤其是在 Windows 中)来确定文件类型,但 unix 通常将文件“扩展名”视为任意文件名的一部分。使它成为可能可执行的 bash 脚本的原因是 shebang 行上该解释器的规范。

我们现在可以从 bash 运行我们的脚本,就像我们编写一个 python 脚本一样。

$ bash hello-world
hello, world!

为了使bash 隐含,我们将文件标记为可执行文件。这使得 linux 操作系统可以参考文件的开头“魔术字节”来确定如何运行它。这些开始字节可能表示 ELF 文件(编译的可执行文件,用例如 C、C++ 或 go 编写)。或者,它可能是#!,恰好意味着“读取第一行的其余部分以确定要运行的命令,并将该文件的其余部分传递给该命令以进行解释。

$ chmod +x hello-world

ls -l 将向我们展示文件上的“权限”(更准确地说是“文件模式”,因此是chmod 而不是chperm)。 x 代表可执行文件,因此我们启用了使用前导字节来确定执行方法。请记住,这个文件的前两个字节,以及第一行的其余部分,然后指定这个文件应该是“通过 bash 运行”,可以这么说。

$ ls -l hello-world
-rwxr-xr-x  1 danfarrell  staff  33 Dec 27 20:02 hello-world

现在我们可以从当前目录运行文件了:

$ ./hello-world
hello, world!

此时,此命令与系统上任何其他命令的唯一区别是您必须指定其位置。那是因为我当前的目录是 not 在系统路径中。简而言之,路径(可在 unix shell 中通过 $PATH 变量访问)指定了一个有序的位置列表,应该搜索未指定位置的指定命令。

例如,有一个非常常见的程序叫做whoami。我可以直接从我的终端运行它,而无需指定可执行文件的位置:

$ whoami
danfarrell

这是因为在我的 $PATH 中有一个位置,shell 可以在其中找到该命令。让我们仔细看看。首先,这是我的路径:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin

还有一个名为whereis 的便捷程序可以帮助显示哪些路径元素提供了一个命名的可执行文件:

$ whereis whoami
/usr/bin/whoami

果然whoami$PATH的元素之一。 (实际上我分享了一个简化的 $PATH。你的可能会更长一些)。

那么,我们终于可以做最后一件事了。如果我将 hello-world 放在 $PATH 元素之一中,我将能够在没有路径的情况下调用它。有两种方法可以做到这一点:我们可以将可执行文件移动到路径中指定的位置,或者我们可以将新位置添加到路径中。为简单起见,我将选择其中的第一个。

$ sudo cp hello-world /usr/local/bin/
Password:

我需要使用 sudo 写入 /usr/local/bin 因为我的用户无法直接访问它 - 这是非常标准的。

最后,我已经实现了能够从任何位置运行我的非常重要程序的目标,而无需指定可执行文件的位置。

$ hello-world
hello, world!

$ which hello-world
/usr/local/bin/hello-world

有效!我创建了可能被描述为“自定义终端命令”的内容。

我所知道的是 $1 是一个 arg 是否可以将其设为变量,然后像在 python 中一样获取第一个字母?

嗯,一种选择是简单地在 python 中编写自定义终端命令。如果python可用,

$ which python
/usr/bin/python

您可以像 shell 一样在 shebang 中指定它:

#!/usr/bin/env python
print("hello, world!"[0])
$ hello-world
h

有效!

好的,忏悔时间。我实际上使用了#!/usr/bin/env python,而不是/usr/bin/pythonenv 帮助找到正确在用户环境中使用的python,而不是硬编码一个特定的python。如果您在长期运行的 python 2 到 python 3 迁移期间一直在使用 python,那么您无疑可以理解为什么我不愿意在我的程序中硬编码 python 可执行文件。

当然可以在 bash 脚本中获取字符串的第一个字母。但也很有可能在 shell 以外的程序中编写自定义命令。如果您知道的话,Python 是字符串操作的绝佳选择。我经常将 python 用于需要与 json 交互的 shell one-liners,这种格式不适合标准的 unix 工具流编辑。

无论如何,以通过重新回答“已回答”的问题而引起 SO 社区的愤怒为代价,我将在 shell 中包含一个版本(感谢 David C Rankin)

#!/bin/bash
echo "${1:0:1}"
$ hello-world hiworld
h

【讨论】:

  • 干得好,写得很好,写到问题的水平。
  • 这是我在堆栈溢出方面收到的最好的认可。谢谢。
猜你喜欢
  • 2013-07-17
  • 2021-04-24
  • 2018-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
相关资源
最近更新 更多