How would you represent EOF in bash?

前端 未结 5 1078
执念已碎
执念已碎 2020-12-24 07:31

I\'m trying to do something like

read -d EOF stdin

for word in $stdin; do stuff; done

where I want to replace \'EOF\' for an actual repre

相关标签:
5条回答
  • 2020-12-24 08:10

    There isn't an end-of-file character really. When you press Ctrl-d or similar characters, the terminal driver signals to the reading application that the end of file has been reached, by returning an invalid value. The same is done by the operation system, when you have reached the end of the file. This is done by using an integer instead of a byte (so you have range similar to -2^16 .. 2^16, instead of only 0..255) and returning an out-of-range value - usually -1. But there is no character that would represent eof, because its whole purpose is to be not a character. If you want to read everything from stdin, up until the end of file, try

    stdin=$(cat)
    for word in $stdin; do stuff; done
    

    That will however read the whole standard input into the variable. You can get away with only allocating memory for one line using an array, and make read read words of a line into that array:

    while read -r -a array; do 
        for word in "${array[@]}"; do 
            stuff;
        done
    done
    
    0 讨论(0)
  • 2020-12-24 08:11

    Two things...

    The EOF character is represented by C-d (or C-v C-d if you want to type it), but to do what you're trying, it's better to do this:

    while read line; do stuff "${line}"; done
    
    0 讨论(0)
  • 2020-12-24 08:26

    litb & Daniel are right, I will just answer your "Just for kick" question: Bash (as any command line unix program in general) only see characters as bytes. So you cannot match Alt-v, you will match whatever bytes are sent to you from the UI (pseudo-tty) that interpret these keypresses from the users. It can even be unix signals, not even bytes. It will depend on the terminal program used, the user settings and all kind of things so I would advise you not try to match them.

    But if you know that your terminal sends C-v as the byte number 22 (0x16), you can use things like:

    if test "$char" = '^V'; then...
    

    by entering a real ^V char under your editor (C-q C-v under emacs, C-v C-v under an xterm , ...), not the two chars ^ and V

    0 讨论(0)
  • 2020-12-24 08:27

    To find what a control character is, run

    $ cat | od -b
    ^D
    0000000 004 012
    0000002
    

    I typed ^V^D after issuing the command, and then RET and another ^D (unquoted) and the result is that EOF is octal 004.

    Combining that result with read(1):

    $ read -d "$(echo -e '\004')" stdin
    foo
    bar quuz^Hx
    ^D
    $ echo "$stdin"
    foo
    bar quux
    $ for word in $stdin; do echo $word; done
    foo
    bar
    quux
    

    Yes, I typed ^H above for backspace to see if read(1) did the right thing. It does.

    0 讨论(0)
  • 2020-12-24 08:29

    My own terminal driver, when getc returns the EOT, fclose's stdout and reopens. That way, when reader's getc senses an empty write queue and returns the EOF (non char value) to signal it's closed, user sub-routines such as the `cat' can shift the argument and eventually quit. Thus renders the EOF a stream condition or file marker, no value in the range of ``char''.

    0 讨论(0)
提交回复
热议问题