How to read from a file or standard input in Bash
The following solution reads from a file if the script is called with a file name as the first parameter $1
and otherwise from standard input.
while read line
do
echo "$line"
done < "${1:-/dev/stdin}"
The substitution ${1:-...}
takes $1
if defined. Otherwise, the file name of the standard input of the own process is used.
How can I read from stdin with this specific command?
In C, reading from "standard input", or stdin
, is the default. It's the easiest thing there is. You don't have to explicitly open anything; stdin
is always opened for you (along with stdout
and stderr
) before your main
function even gets called.
You can read from stdin
with a variety of standard library functions. The most common are getchar
and scanf
. And, to repeat: you can just start calling them, on the first line of main
, if you like. They work right away; there are no setup steps required.
getchar
reads one character.scanf
reads "formatted input", although this function is full of problems and gotchas, to the point that it's almost not worth using.
To read one line from stdin
, the function used to be gets
, although it had a fatal problem and has been removed from the language. Today, to read one line from stdin
, one way to do it is with the fgets
function, which can actually read lines from any stream, so you have to explicitly pass it stdin
as its fp
argument.
How to continuously read from stdin (not just once input file is done)?
In addition to print(x, flush=True)
you must also flush after sys.stdout.write
.
Note that the programs would technically work without flush, but they would print values very infrequently, in very large chunks, as the Python IO buffer is many kilobytes. Flushing is there to make it work more real-time.
sys.stdout.write(str(count))
sys.stdout.flush()
How to read input from Stdin with fork()
OK; sounds straight-forward — at least, as long as you're typing the input. In fact, it is hard to make it go wrong. What did you try and what happened when you tried it? Please read up on how to create an MCVE (Minimal, Complete, Verfiable Example).
However, it gets (a lot) trickier when you're reading from a file. The problem is that when you read from the terminal, the standard I/O routines in the child get the first line of data and then let the process work with that. The child exits without reading the second line, so the parent can pick up where the child left off. If, instead, you're reading from a file, the standard I/O routines read a buffer full of data, which can be many lines. And what the child reads, the parent can't. So, what works with terminal input doesn't work with file input.
How can you avoid the problem? 'Tis hard. One possibility, which would probably be regarded as cheating, is to have the initial (parent) process read one character before forking. This fills the buffer with one line if the input is coming from a terminal, or with the initial buffer full if reading from file. After forking, the child process can read the first line (fgets()
) and print it and exit. Meanwhile, the parent process also has the first line of data in its copy of the input buffers (remember, the forked child and parent are almost identical after forking), so it can read and ignore the first line (the child is processing that), and then read and print the remaining lines. It can then wait for the child to die in a loop, and finally read the remaining lines. This leads to:
/* SO 4263-5451 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
int c = getchar();
if (c == EOF)
{
fprintf(stderr, "Standard input was empty!\n");
exit(1);
}
ungetc(c, stdin);
//setvbuf(stdin, 0, _IOLBF, 0);
if ((pid = fork()) < 0)
{
fprintf(stderr, "Failed to fork()!\n");
exit(2);
}
if (pid == 0)
{
/* Child */
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
{
fprintf(stderr, "Failed to read line in child\n");
exit(3);
}
line[strcspn(line, "\n")] = '\0';
printf("Child: read [%s]\n", line);
exit(0);
}
else
{
int corpse;
int status;
while ((corpse = wait(&status)) > 0 && corpse != pid)
printf("Parent: child %d died with status 0x%.4X\n", corpse, status);
char line[4096];
if (fgets(line, sizeof(line), stdin) == 0)
{
fprintf(stderr, "Failed to read line in parent\n");
exit(4);
}
while (fgets(line, sizeof(line), stdin) != 0)
{
line[strcspn(line, "\n")] = '\0';
printf("Parent: read [%s]\n", line);
}
}
return 0;
}
This yielded:
Child: read [Monday]
Parent: read [Tuesday]
Parent: read [Wednesday]
I tried a variant setting line-buffering with setvbuf(stdin, 0, _IOLBF, 0);
but that didn't affect the file input (on a Mac running macOS Sierra 10.12.3 with GCC 6.3.0), though it too worked fine with terminal input.
One option would be to replace the standard I/O functions with file descriptor code, and to use read(STDIN_FILENO, &c, 1)
to read characters one at a time. This is slower (lots of system calls) but reliable:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static int input_char(int fd)
{
char c;
if (read(fd, &c, 1) != 1)
return EOF;
return c;
}
static size_t input_line(int fd, char *buffer, size_t buflen)
{
int c;
size_t bufcnt = 0;
while (bufcnt < buflen - 1 && (c = input_char(fd)) != EOF)
{
if (c == '\n')
break;
buffer[bufcnt++] = c;
}
buffer[bufcnt] = '\0';
return bufcnt;
}
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
{
fprintf(stderr, "Failed to fork()!\n");
exit(2);
}
if (pid == 0)
{
char line[4096];
if (input_line(STDIN_FILENO, line, sizeof(line)) == 0)
{
fprintf(stderr, "Failed to read line in child\n");
exit(3);
}
printf("Child: read [%s]\n", line);
exit(0);
}
else
{
int corpse;
int status;
while ((corpse = wait(&status)) > 0 && corpse != pid)
printf("Parent: child %d died with status 0x%.4X\n", corpse, status);
char line[4096];
while (input_line(STDIN_FILENO, line, sizeof(line)) != 0)
{
printf("Parent: read [%s]\n", line);
}
}
return 0;
}
How to read input from the command line's standard input in Python?
This is a very simple loop that stores whatever input you give in lines
when last 2 lines are empty i.e lines[-1]==lines[-2]==""
then break;
[just mak sure that you have taken at least 2 inputs from the user so check len(lines)>2
]
lines = []
while True:
inp = input()
lines.append(inp.strip())
if len(lines)>2 and lines[-1]==lines[-2]=="":
break
print('\n'.join(lines))
A
B
C
A B 2
A C 3
C B 4
A B 1
If you don't want to store all the lines
lines = ['temp', 'temp']
while True:
inp = input()
lines[-2], lines[-1] = lines[-1], inp.strip() # this changes the second last element by last one and the last one is updated to the new line that is entered
if lines[-1]==lines[-2]=="":
break
Related Topics
How to Use Threading in Python
Why Can a Function Modify Some Arguments as Perceived by the Caller, But Not Others
Convert a String Representation of a Dictionary to a Dictionary
How to Read/Process Command Line Arguments
Pip' Is Not Recognized as an Internal or External Command
Unboundlocalerror on Local Variable When Reassigned After First Use
Dealing With Multiple Python Versions and Pip
What Are the Differences Between Type() and Isinstance()
How Are Iloc and Loc Different
Use Different Python Version With Virtualenv
Getting the Name of a Variable as a String
How to Get a Cron Like Scheduler in Python
How to Watch a File For Changes
Get Statistics For Each Group (Such as Count, Mean, etc) Using Pandas Groupby