[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] multiline random paste or how to properly use (named) st
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] multiline random paste or how to properly use (named) streams |
Date: |
Tue, 13 Mar 2018 12:57:45 -0400 |
User-agent: |
NeoMutt/20170113 (1.7.2) |
On Tue, Mar 13, 2018 at 04:49:47PM +0100, Garreau, Alexandre wrote:
> Recently a friend of mine asked me if I would have a right away solution
> to interleaves line of a file foo and a file bar (m3u files actually),
Music play lists. Good. Having the context is helpful. An m3u file
has one filename per line (either CR-LF or newline terminated), as I
understand it. No blank lines, no markup or groupings or comments or
anything else.
> in a way that each (at random) 1 to 5 lines of “foo” would be surrounded
> by (at random) 2 to 4 (preferably but not necessarily) random unique
> (not appearing several times in total) lines of “bar”
When you say "surrounded by", do you actually mean "followed by"?
So, as I understand it, the problem is as follows:
1) We have two text files containing multiple lines. There is no semantic
meaning to the lines (they are filenames, but we're not going to be
opening or statting the files). They are of roughly equal sizes.
2) The first file is to be used in sequential order. The second file is
to be randomly shuffled.
2a) A recent GNU coreutils is available for the shuffling.
3) A single output file is to be produced, containing lines from both
input files, following a sequence of steps. At each step, read 1-5
lines from the first file, and write them to the output. Then read
2-4 lines from the (shuffled) second file, and write those to the
output.
If this is the full problem spec, then here's one approach:
#!/bin/bash
exec 3< file1
exec 4< <(shuf file2)
while true; do
# Read 1-5 lines from first file.
n=$((1 + RANDOM%5))
for ((i=1; i<=n; i++)); do
IFS= read -r line <&3 || break
printf %s\\n "$line"
done
# Read 2-4 lines from second file.
n=$((2 + RANDOM%3))
for ((i=1; i<=n; i++)); do
IFS= read -r line <&4 || break
printf %s\\n "$line"
done
done
exec 3<&- 4<&-
This terminates as soon as it reaches EOF in either file. This may
cause some lines from the *other* file (whichever one didn't hit EOF)
to be unused. If that's a problem, well, you can fix it. ;-)