Ruby:使用“-n”选项执行shell命令'echo'

6
我希望您能从Ruby运行以下shell命令,将字符串复制到剪贴板(在OS X上),'n'可以抑制由echo引起的字符串后面的换行符:
echo -n foobar | pbcopy

—>工作正常,现在剪贴板包含“foobar”

我尝试了以下方法,但它们所有的方法都会将选项“-n”一起复制到剪贴板中:

%x[echo -n 'foobar' | pbcopy]
%x[echo -n foobar | pbcopy]
system "echo -n 'foobar' | pbcopy"
system "echo -n foobar | pbcopy"
exec 'echo -n "foobar" | pbcopy'
`echo -n "foobar" | pbcopy`
IO.popen "echo -n 'foobar' | pbcopy"

什么是实现这个的正确方式?
5个回答

7

你的问题在于-n只能被bash内置的echo命令理解;当你使用%x[...](或者其他类似的变体)时,该命令会被传递给/bin/sh,即使它实际上是/bin/bash,它也会像一个POSIX shell一样运行。解决方案是明确地将你的shell命令传递给bash:

%x[/bin/bash -c 'echo -n foobar' | pbcopy]

当然,你需要小心引用任何真正的foobar-c 开关基本上告诉/bin/bash,你正在给它一个内联脚本:

-c string
如果有-c选项,则从字符串中读取命令。 如果字符串后面还有参数,则将它们分配给位置参数,从$0开始。


谢谢!这看起来就是我想要的。我正在复制的字符串是用户指定的密码,通常会进入一个密码字段,这就是为什么我不能复制换行符的原因,因为它不一定会显示为换行符,而是作为额外的字符。您对此有其他建议吗? - polarblau
1
如果你正在传递密码,那么使用其中一种popen方法打开pbcopy并通过stdin发送密码可能更可靠,因为你不必担心引号。 Tin Man有一个使用stdin和Open3.popen3()的示例。 - mu is too short
%x[/bin/echo -n foobar | pbcopy]”不是更简单吗?(顺便说一句,“%x[echo -n foobar | pbcopy]”对我来说似乎也可以。) - matt
@matt:是的,%x[...] 这个方法很好用,而且简单明了。但问题在于,“foobar”可能实际上是“ha'ha$PATH”或其他一些混乱的字符(毕竟这是一个密码),所以你必须确保所有内容都被正确转义。直接打开到 pbcopy 的管道可以避免这个问题。 - mu is too short

6

由于不同的shell和/bin/echo中echo的行为不同,建议您使用printf

无换行符:


%x[printf '%s' 'foobar' | pbcopy]

带有换行符:

%x[printf '%s\n' 'foobar' | pbcopy]

2

你可能正在重复造轮子。

IRB_Tools和Utility_Belt都用于调整IRB,提供了使用剪贴板的功能。它们都是现有宝石的集合,因此我使用gem clipboard -r进行了快速搜索,并找到了:

clipboard (0.9.7)
win32-clipboard (0.5.2)

查看 RubyDoc.info 的 clipboard,可以得知:

clipboard

访问剪贴板而不必关心操作系统是 Linux、MacOS 还是 Windows。

用法

你可以使用 Clipboard.copy、Clipboard.paste 和 Clipboard.clear。

尽情享受;)


编辑:如果你在链接页面中检查源代码,你会发现在 Mac 上进行复制的方式如下:

def copy(data)
  Open3.popen3( 'pbcopy' ){ |input,_,_| input << data }
  paste
end

并且对于粘贴,你会看到:
def paste(_ = nil)
  `pbpaste`
end

并且清晰就是简单明了:

def clear
  copy ''
end

这些应该能让你朝着正确的方向前进。

谢谢!我可能会看一下源代码,但是这个宝石可能有点过于强大了。 - polarblau

1
这可能看起来像是一个丑陋的解决方法,但我非常确定它会起作用:
创建一个名为myfoobar.sh的可执行文件,其中包含您想要执行的命令行。
#! /bin/sh
echo -n foobar | pbcopy

然后从 Ruby 中调用该文件。


1
只有当/bin/sh是bash(或其他支持echo -c的shell)并且配置为像bash而不是严格的POSIX shell时,此方法才有效。 /bin/sh通常被配置为像严格的POSIX shell一样运行。另一方面,如果你使用#!/bin/bash,那么使用echo -n将会得到更一致的结果。 - mu is too short
谢谢,但无论如何我想避免在这种情况下使用额外的文件。 - polarblau

0

使用sutil进行正确设置:

    $ ssh-copy-id user@host


1
这个命令是关于如何"在远程机器的authorized_keys中安装您的公钥",但问题是关于将一个字符串复制到剪贴板上。您能否解释一下这是如何解决问题的? - Simon MᶜKenzie

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