我需要将包含斜杠的字符串传递给 sed 以从中提取一些值,但是当我尝试这样做时,它会将其视为目录/文件并抛出“没有这样的目录或文件”错误。我假设这是因为它将其读取为路径,并在不是预期效果时尝试查找该文件。例子:
my_value="my/value"
operand="$($my_value | sed -n -e 's/^\(.*\)\/.*/\1/p')"
# Expected echo $operand : my
注意:我是 bash 脚本新手,所以这可能是错误的方法
答案1
如果您希望 的输出echo $operand
为my
,那么您的语法就很好,除了缺少一件事:
operand="$(echo $my_value | sed -n -e 's/^\(.*\)\/.*/\1/p')"
您需要使用echo
该my_value
变量,以便将其值发送到 stdout 以sed
对其进行操作。您收到错误是因为实际上没有调用my/value
作为变量值的文件或目录。
上述operand
变量的命令替换包括将在使用时echo
输出。my
echo $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 中使用参数扩展可以处理路径名包含换行符的情况。