如何将来自stdin的文本接收到升华文本编辑器中?有了vim,它的工作原理是这样的:
echo "potato potato potato" | vim -
同样的事情也适用于gedit,创建一个包含内容的新文档。
Sublimeterxt似乎刚刚开始在一个新的选项卡中编辑一个名为"-"的文件,还有其他一些shell技巧可以奏效吗?
假设Sublime仍然不支持打开STDIN,一个简单的解决方案是将输出转储到一个临时文件,在Sublime中打开该文件,然后删除该文件。假设您在bin目录中创建了一个名为tosubl
的脚本,如下所示:
#!/bin/bash
TMPDIR=${TMPDIR:-/tmp} # default to /tmp if TMPDIR isn't set
F=$(mktemp $TMPDIR/tosubl-XXXXXXXX)
cat >| $F # use >| instead of > if you set noclobber in bash
subl $F
sleep .3 # give subl a little time to open the file
rm -f $F # file will be deleted as soon as subl closes it
然后你可以通过做这样的事情来使用它:
$ ps | tosubl
但是,如果您的shell支持Process Substitution(它可能支持),那么一个更有效、更可靠的解决方案将是使用它。这样就省去了临时文件。这是bash:
tosubl() {
subl <(cat)
}
echo "foo" | tosubl
我很确定你可以以某种方式删除cat
在该函数中的使用,在该函数中将比特从stdin冗余地铲送到stdout,但目前我无法理解在该上下文中这样做的语法
我不知道Sublime Text,但您的问题应该是通用的,因为它适用于任何接受文件名作为参数但拒绝从stdin读取的程序。
幸运的是,Bash允许您将stdout从一个进程管道传输到某种临时文件中,然后将该文件的名称传递给另一个进程。
来自man bash
:
在支持命名管道(FIFO)或命名打开文件的/dev/fd方法的系统上支持进程替换。它采用<(列表)或>(列表)。进程列表在其输入或输出连接到FIFO或/dev/fd中的某个文件的情况下运行。作为扩展的结果,此文件的名称将作为参数传递给当前命令。如果使用>(列表)表单,则写入文件将为列表提供输入。如果<(list)形式时,应读取作为参数传递的文件以获得list的输出。
假设SomeProcess生成要在编辑器中捕获的输出:
sublimetext <(SomeProcess)
或:
SomeProcess | sublimetext <(cat)
如果您认为您将大量手动输入,那么您可能需要将sublimetext <(cat)
放入shell脚本或别名中。
万一你的操作系统不支持进程替换,那么你当然可以自己指定一个临时文件:
SomeProcess > /tmp/myoutput
sublimetext /tmp/myoutput
您可能会发现更多实用程序中的vipe
非常有用。如果你已经设置了EDITOR='subl --wait'
,你可以简单地:
echo 'potato potato potato' | vipe
从版本4开始,SublimeText支持从stdin管道输入。
来自变更日志:
构建4063
命令行:
subl -
现在可以用于从stdin读取所有平台
更新!只有在MacOS上:截至4109
subl现在可以用于编辑stdin,例如:echo-test|subl|cat
清管https://stackoverflow.com/a/31035834/2429912有一点,因为对我来说,它能做到90%,但不是全部:
使用临时文件是一种几乎可以与任何编辑器一起使用的方式。更好的是,如果编辑器支持等待文件关闭(对于Sublime Text,sublime -w
),您实际上可以动态编辑它,这使它更加通用。要做到这一点,您需要更改PATH中名为tosubl
的脚本@tylerl提供的脚本:
#!/bin/bash
TMPDIR=${TMPDIR:-/tmp} # default to /tmp if TMPDIR isn't set
F=$(mktemp $TMPDIR/tosubl-XXXXXXXX)
cat >| $F # use >| instead of > if you set noclobber in bash
subl -w $F # waits until the file is closed
cat $F # prints out the contents of the file to stdout
rm -f $F # clean up the file
现在运行echo "hello" | tosubl > local.file
将打开Sublime中第一个脚本的输出,关闭后将其保存到local.file
。
如果您想用ANSI转义序列(例如终端缓冲区)显示彩色文本,您可以安装包ANSIescape并使用以下命令:
F=$(mktemp); cat > $F; subl $F; subl --command ansi; sleep .5; rm -f $F
好吧,现在是2020年,sublime仍然无法(不会?)从stdin读取。由于程序的原因,这个线程中没有一个答案对我来说是令人满意的。
就我而言,我想利用";将当前选择粘贴到程序中";kitty终端模拟器的功能。该功能会获取终端中的当前选择,并在按下键盘快捷键时将其管道传输到程序中。出于某种原因,kitty的开发人员决定将选择作为参数而不是通过stdin传递。
为了解决这个问题,我写了一个小的C脚本,可以处理这两种情况。为了运行该脚本,您需要安装TCC。您可能需要先检查您的回购。我知道你可以在debian上安装apt:sudo apt install tcc
。或者,您可以使用GCC编译以下代码,只需删除第一行即可。
#!/usr/bin/tcc -run
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
uint64_t randVal = 0;
FILE *fp = fopen("/dev/urandom", "rb");
fread((char *) &randVal, 8, 1, fp);
fclose(fp);
char tmpfile[512] = {0};
sprintf(tmpfile, "/tmp/piped_input_%llu.txt", randVal);
fp = fopen(tmpfile, "wb");
if(!fp)
{
fprintf(stderr, "Could not open temporary file: '%s'n", tmpfile);
return -1;
}
if(argc == 2)
fprintf(fp, "%s", argv[1]);
if(argc == 1)
{
uint8_t tmpBuf[4096] = {0};
memset(tmpBuf, 0, 4096); // Old habit... ¯_(ツ)_/¯
while(!feof(stdin))
{
int32_t numRead = fread((char *) tmpBuf, 1, 4096, stdin);
if(numRead > 0)
fwrite((char *) tmpBuf, numRead, 1, fp);
else
break;
}
}
fflush(fp);
fclose(fp);
char cmdStr[512] = {0};
sprintf(cmdStr, "subl %s", tmpfile);
system(cmdStr);
// Give sublime some time to open the file
usleep(1000 * 250);
unlink(tmpfile);
return 0;
}
除非将参数传递给程序,否则上述脚本将从stdin读取。在任何一种情况下,它都只需将输入(stdin
或argv[1]
)读取到一个临时文件中,用sublime打开该文件,等待~250ms以给sublime时间打开文件,然后删除临时文件。
您可以将上面的代码复制到路径中的某个位置(如/usr/local/bin/subl_pipe)。确保设置了权限:chmod 755 /usr/local/bin/subl_pipe
。
不管怎样,我希望这最终对其他人有用…^_^
有一种简单的方法:您可以将输入管道传输到Sublime Text(版本4121及以上),因为它支持从STDIN:读取
cat file.txt | subl -