1

I have a dictionary program, sdcv, that outputs either normal text or HTML, and I'm writing a Bash script that normalizes the output so that it simply prints stdout if sdcv is writing normal text or it prints formatted HTML using lynx if sdcv is outputting HTML.

For that purpose, I'm trying to make a Bash script I can pipe to using sdcv MYWORD | myscript.sh that will analyze sdcv's output. The problem is that sdcv has two outputs, and I need to format the second one on the basis of the first one. After the first output, sdcv requires user input, and then prints the second output.

I've tried using FIRST_OUTPUT=$(tee /dev/tty), but the problem is that this amalgamates sdcv's first output, my input requested by sdcv, and sdcv's second output, and I don't have access to anything until I've entered the input.

How could I proceed?

7
  • 2
    expect maybe. Commented Oct 8, 2023 at 14:52
  • @KamilMaciorowski woah, that is an extremely handy program! thank you very much!
    – shintuku
    Commented Oct 8, 2023 at 15:10
  • If you want something post-processable, maybe use its -j option. Commented Oct 8, 2023 at 15:25
  • So you want the "Found NN items, similar to WORD. .... Your choice" as input one and the result of choice as input two?
    – ibuprofen
    Commented Oct 8, 2023 at 16:20
  • If you only want part two you can set your script as pager. Typically SDCV_PAGER=./my_script sdcv WORD the script will get the result as stdin, - but from what you write it sounds like you want both. Is this correct?
    – ibuprofen
    Commented Oct 8, 2023 at 16:22

2 Answers 2

0

Maybe you can just pipe the sequences of lines that start with <html... and end with </html... to that lynx (or maybe better elinks or w3m) command.

Like:

#! /usr/bin/perl
while (<<>>) {
  if (!$inhtml && m{<html}i) {
    $inhtml = 1;
    open HTML, "|-", qw(elinks -dump);
  }

  print {$inhtml ? HTML : STDOUT}  $_;

  if ($inhtml && m{</html}i) {
    close HTML;
    $inhtml = 0;
  }
}

(and sdcv MYWORD | that-script)

1
  • Unfortunately I still need to handle the input prompt!
    – shintuku
    Commented Oct 8, 2023 at 16:58
0

This ended working for me, the answer was a painful journey through expect. I have no doubt there's room for improving this code, so feel free to leave your suggestions!

#!/usr/bin/expect -f

set arg1 [lindex $argv 0]
spawn sdcv $arg1

expect "Found*" {

    expect "Your choice*" {
        expect_user -re "(.*)\n"

        set user_input $expect_out(0,string)
        send "$user_input\r"

        expect "#"
        set output $expect_out(buffer)

        set command "echo \"$output\" | lynx --dump --stdin"

        spawn bash
        expect "*"

        send "$command\r"
        expect "$command\r\n"

        expect eof
    }

    #for some reason gets saved to expect_out(0,string) when we input a word with a single match
    set output $expect_out(0,string)
    set command "echo \"$output\" | lynx --dump --stdin"

    spawn bash

    send "$command\r"
    expect "$command\r\n"

    expect eof
}
1
  • Update a day later: for me, the Python pexpect library is considerably more intuitive and easier to use, and achieves the same result
    – shintuku
    Commented Oct 9, 2023 at 13:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .