如何将包含斜杠的字符串传递给 sed 而不将其视为文件? (没有这样的目录或文件)

如何将包含斜杠的字符串传递给 sed 而不将其视为文件? (没有这样的目录或文件)

我需要将包含斜杠的字符串传递给 sed 以从中提取一些值,但是当我尝试这样做时,它会将其视为目录/文件并抛出“没有这样的目录或文件”错误。我假设这是因为它将其读取为路径,并在不是预期效果时尝试查找该文件。例子:

my_value="my/value"

operand="$($my_value | sed -n -e 's/^\(.*\)\/.*/\1/p')"

# Expected echo $operand : my

注意:我是 bash 脚本新手,所以这可能是错误的方法

答案1

如果您希望 的输出echo $operandmy,那么您的语法就很好,除了缺少一件事:

operand="$(echo $my_value | sed -n -e 's/^\(.*\)\/.*/\1/p')"

您需要使用echomy_value变量,以便将其值发送到 stdout 以sed对其进行操作。您收到错误是因为实际上没有调用my/value作为变量值的文件或目录。

上述operand变量的命令替换包括将在使用时echo输出。myecho $operand

另一种方法是:

operand="$(printf '%s\n' "$my_value" | sed -n -e 's/^\(.*\)\/.*/\1/p')"

这是更好的情况之一printf,以便 echo 不会对包含的其他字符串进行操作。在这种情况下不会发生,但在其他情况下可能会发生。

答案2

您构建的管道依赖于一个命令的输出作为另一个命令的输入。您正在尝试执行一个名为 的文件my/value,并且可能被告知没有这样的文件。

有多种方法可以做你想做的事。

这种方法仍然使用管道,可能是最可移植的。

operand="$(echo "$my_value" | sed -n -e 's/^\(.*\)\/.*/\1/p')"

如果你的 shell 支持它,这是一个替代方案(至少应该在 bash 中工作):

operand="$(sed -n -e 's/^\(.*\)\/.*/\1/p' <<< "$my_value")"

后一种方法稍微更可取,因为它不会调用额外的过程来显示变量值。

无论哪种情况,最好用双引号保护变量内容。

答案3

正如其他人所指出的,您正在尝试$my_value在命令替换中将 的值作为命令执行。

如果您想删除/字符串中第一个之后的所有内容,请使用命令替换:

my_value="this/is/my/value"
operand=${my_value%%/*}

printf '%s\n' "$operand"    # will output the string "this"

参数扩展${my_value%%/*}将导致最长的后缀字符串匹配/*从 value 中删除$my_value。这是一个标准参数扩展并且 shell 的执行速度比调用快得多sed

另外,如果 in 的$my_value值为路径名,那么使用sed它来操作它就会很危险,因为它在技术上可能包含换行符。在 shell 中使用参数扩展可以处理路径名包含换行符的情况。

相关内容