将IPython变量作为参数传递给bash命令

163
我如何在Ipython/Jupyter笔记本中执行bash命令,将Python变量的值作为参数传递,就像这个例子一样:

py_var="foo"
!grep py_var bar.txt

(显然我想要用 grep 来查找 foo 而不是字面字符串 py_var)


可能是如何将命令行参数传递给IPython的重复问题。 - Amrith Krishna
2
@AmrithKrishna:不是很对。请看编辑。 - Unni
跟进:我想使用关键字参数,例如 ffmpeg -i <inputfilename> ...,但是下面的答案在这种命令中无法正常工作。你知道有没有其他解决方案吗? - axolotl
@Aalok:编辑后的答案怎么样?现在可以检查一下吗?如果不起作用,请发布您正在尝试运行的完整命令。 - Unni
对于那些想要将Python变量传递给bash单元格(魔法%%bash)的人,请参见此问题 - C. Binair
4个回答

227

通用解决方案

如Catbuilts所建议,使用{..}

dir_path = "/home/foo/bar"
!cp file1 {dir_path}

它的行为比$..更可预测。例如,如果您想将另一个字符串sub_dir连接到路径中,则$无法给出预期结果,而使用{..},您可以执行以下操作:

!cp file1 {dir_path + sub_dir}

初步(已编辑)回答

对于简单情况,您可以在您的变量名称前加上$

例子

比如您想要将文件file1复制到存储在Python变量dir_pth中的路径:

dir_path = "/home/foo/bar"
!cp file1 $dir_path

从Ipython或Jupyter笔记本中

如上所述,需要注意,根据您的变量内容和关联方式可能会导致意外结果,因此应优先考虑通用解决方案。

原始字符串

有关使用原始字符串(以r为前缀)传递变量的讨论,请参见将Ipython变量作为字符串参数传递给shell命令


1
不要忘记将自己的答案标记为已接受的答案;-) 这有助于在StackOverflow上保持“清洁”。 - Oliver W.
5
虽然 !cp file1 $dir_path!cp file1 {dir_path} 的结果相似,但我发现使用 $ 有一定的风险。因为用 {} 时,你可以连接路径,例如:!cp file1 {folder + dir_path},而 !cp file1 $folder + $dir_path 可能会删除你的 folder 文件。要小心。 - Chau Pham
4
如果变量中有空格,请不要忘记加上引号!例如,如果变量为dir_path ="/home dir/foo/bar",则应像这样使用引号:!cp file1 "$dir_path"。这将在Bash命令中添加引号。 - Matt Bussing
1
当IPython变量被插入到shell字符串中时,以下是实现此操作的方法:https://dev59.com/PlsW5IYBdhLWcg3wCDXF - SeaDude
5
提醒 Colab 用户:在 Google Colab 笔记本中,变量标记 **{variable} 并不像之前一样工作。如果您的 Python variable 包含空格或任何破坏 cmd 行命令的内容,则仍需要将其括在引号中。因此使用 !cp file1 "{dir_path}"。多个变量的值相加是有效的,但如果其中可能含有空格,则需要在引号中添加:!cp "{filename + filename}" "/content/drive/My Drive/" - aneroid
显示剩余7条评论

14

你也可以使用这种语法:

path = "../_data/"
filename = "titanicdata.htm"
! less {path + filename}

非常好。谢谢! - tzelleke

3

正如@Catbuilts所指出的那样,$符号是有问题的。为了更加明确并不掩盖关键示例,可以尝试以下操作:

afile='afile.txt'
!echo afile
!echo $PWD
!echo $PWD/{afile}
!echo {pwd+'/'+afile}

你将获得:

afile.txt
/Users/user/Documents/adir
/Users/user/Documents/adir/{afile}
/Users/user/Documents/adir/afile.txt

2
在一个命令中同时使用Python和环境变量并没有简单的解决方案。作为一种解决方法,我们可以创建一个字符串变量,如下所示: command = f"echo $PWD/{afile}" !{command} - Dmitry Balabka

0

只是一个补充。在我的情况下,正如这个问题中的一些示例所示,我的参数是带有空格的文件名。在这种情况下,我必须使用稍微不同的语法:"$VAR"。例如:

touch "file with spaces.txt"
echo "this is a line" > "file with spaces.txt"
echo "this is another line" >> "file with spaces.txt"
echo "last but not least" >> "file with spaces.txt"
echo "the last line" >> "file with spaces.txt"
cat "file with spaces.txt"

# The variable with spaces such as a file or a path
ARGUMENT="file with spaces.txt"
echo $ARGUMENT

# The following might not work
cat $pwd$ARGUMENT

# But this should work
cat $pwd"$ARGUMENT"

希望这能帮到你。;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接