文字列をttyに入れてコマンドを作成します


15

私はこれをどうにかして

echo -n " command "> / dev / tty1

文字は表示され、カーソルは移動しますが、それらは「ゴースト」です。ヒットするとEnter、何も起こりません(標準入力ではありません)。

編集:

下のスクリーンショットの真ん中に、私がこれを使用する理由がわかります。(赤いキャプションが付いた行、黄色のキャプションが付いた行のすぐ下。)今のままでは、実際にはノートテキストを「編集」していません。新しいテキストを書くように求められます。これは、編集中の(実際には)ノートのテキストを置き換えます。したがって、古いテキストをttyに貼り付けるだけで改善できると考えました。ユーザーがEnterキーを押しても、変更は行われません。(このプログラムはPerl / MySQLにありますが、「Perlでこれを行う方法」よりも一般的な解決策を求める方が面白いと思いました。)

例

編集2:

以下は、以下のCコード(意図したとおりに動作します)を使用するPerlコードと、新しいスクリーンショットです。これにより、疑いの余地がないことがわかります。ノートテキストに-今回は古いテキストがあります。たとえば、タイプミスを修正したいだけの場合、ノートテキスト全体を再入力する必要はありません。

my $edit_note_text = $edit_note_data[2];
print BOLD, RED, " new text: ", RESET;
system("writevt /dev/tty \"$edit_note_text\"");
my $new_text = <$in>;
$new_text = fix_input($new_text);
my $set_text = "UPDATE notes SET note = \"$new_text\" WHERE id = $edit_note_id";
$db->do($set_text);

better_example


興味があるなら、Stack OverflowでPythonでこれを行いました。stackoverflow.com/a/29616465/117471
ブルーノブロノスキー

問題の記述は明確ではありません。何が問題ですか?

回答:


3

私はちょうどwritevtそれがトリックを行うと呼ばれる小さなCプログラムを見つけました。ここでソースコードを入手しますgcc最初に次の行を削除するだけでコンパイルするには:

#include <lct/cline.h>
#include <lct/utils.h>

更新します。コマンドは現在の一部であり、コンソール・ツールお使いのディストリビューションが使用する場合を除き、より最近のシステムではこのように利用できる、のkbdの代わりに、コンソール・ツールあなたからそれをコンパイルすることができ、その場合には、ソース(はるかに最新のバージョン、必要に応じて変更なし)。

使用法:

sudo writevt /dev/ttyN command 

何らかの理由で、リターンを送信するために'\r'(または'\x0D')の代わりに'\n'(または'\x0A')を使用する必要があることに注意してください。


これは機能しますが、それらのインクルードよりももっと間違っています。私が作る、利用機能を捨てなければならなかったprogname_していくつかの関数呼び出しを、コメントアウトmain()
マイケルMrozek

@MichaelMrozekこの_()関数は通常、使用されているgettextの兆候です。このような単純なデモコードでは少しやり過ぎのように見えますが、害はないと思います。
jw013

上記の回答のリンクが壊れています。私はwritevt.c ここで別のものを見つけました(github.com/  grawityで ; 本質的に同じプログラムのようです。
G-Manが「Reinstate Monica」と言います

私には機能しません-コマンドのみを印刷します。\ rまたは\ n prinst rnを、理由が何であれ、さりげなく待っています; /
Antoniossss

10

端末は、入力デバイス(キーボードなど)と表示デバイス(モニターなど)の2つの役割を兼ねています。端末から読み取ると、入力デバイスからの情報が得られます。端末に書き込むと、データはディスプレイデバイスに送られます。

端末への入力を強制する一般的な方法はありません。これを行う必要はほとんどありません。端末を必要とするプログラムと対話する必要がある場合は、ExpectEmptyなどの専用端末エミュレーター、またはScreenTmuxなどのプログラム可能な端末ラッパーを使用します。ioctlを使用して、Linuxコンソールへの入力を強制できますxdotoolxmacroなどのツールを使用して、X11ターミナルエミュレーターに強制的に入力できます。


投稿を編集しました。ご覧ください。私の考えがわかります。
エマニュエルベルク

@EmanuelBergあなたの編集は理解しにくいです。また、インタラクティブに使用しているプログラムにプログラムで入力をしようとしていますか?それが望むなら、screenまたはtmuxでプログラムを実行し、それらのstuff(画面)またはsend-key(tmux)コマンドまたはそれらの貼り付けバッファー機能を使用します。
ジル「SO-悪であるのをやめる」

Perlコードを含めて2回目の編集を行いました-Cバイナリの呼び出しがあります。私は知りません...それはとても簡単だったので(コードを1行だけ)-あなたのやり方で(screenまたはtmuxツールで)本当にする方が良いですか?
エマニュエルベルク

@EmanuelBergええ、あなたは探していscreen -X stuff 'note version one'ます。
ジル「SO-悪であるのをやめる」

7

少なくともLinuxおよびBSDには、文字を端末入力バッファーにプッシュバックするためのTIOCSTI ioctlがあります(制限[Linuxで最大4096文字])。

#include <sys/ioctl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>

void stackchar(char c)
{
  if (ioctl(0, TIOCSTI, &c) < 0) {
    perror("ioctl");
    exit(1);
  }
}
int main(int argc, char *argv[])
{
  int i, j;
  char c;

  for (i = 1; i < argc; i++) {
    if (i > 1) stackchar(' ');
    for (j=0; (c = argv[i][j]); j++) {
      stackchar(c);
    }
  }
  exit(0);
}

コンパイルして、次のように呼び出します。

cmd foo bar < "$some_tty"

ttyでキャラクターを押し戻す

そしてperlで:

require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;

編集:私は今それがwritevtソリューションと同じioctlだと気づきました。TIOCSTIはVTだけでなく任意の端末で機能するため、コマンドのコメントと名前は誤解を招く可能性があります。


質問の2回目の編集をご覧ください。@htorから取得したコードは既にコンパイル済みです。見たところ、すばらしい結果が得られています。代わりにこのコードを使用して利点を確認できますか?(しかし、どちらの場合でもあなたの努力に感謝します。)
エマニュエルベルク

はい。最近の編集をご覧ください。ポイントはTIOCSTI ioctlを使用することです。私が与えたコードは、ファイル記述子0(stdin)でそれを行います。
ステファンシャゼル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.