On Sat, Aug 31, 2019 at 09:26:49AM -0400, The Wanderer wrote:
> On 2019-08-31 at 09:02, Roberto C. Sánchez wrote:
> 
> > The only time you need to change the syntax is to add something
> > before sed.  But then, that's why shells have I/O redirection:
> > 
> > (sed 's/config=.*$/config=/g' | tr -d '=') <~/test.txt
> > >~/other_test.txt
> 
> This is *far* more complicated and messy, both syntactically and to type
> in, than just having cat at the beginning of a pipeline.
> 
That's quite a stretch.

Your way:

cat ~/test.txt | sed 's/config=.*$/config=/g' | tr -d '=' >~/other_test.txt

A better way:

(sed 's/config=.*$/config=/g' | tr -d '=') <~/test.txt >~/other_test.txt

The better way is actually simpler.  It places all the logic for what is
happening at the start of the line and the I/O redirection (which is
basically just fluff) to the right.  Your way requires that I look at it
for several moments to separate the I/O supporting pieces from the
actual interesting command logic.  The better way has a clean visual
separation.

> It also loses an important benefit when building and tweaking such
> pipelines by hand: convenience of editing. In most shells with which I
> have any experience, command history will place the cursor at the end of
> the remembered line.
> 

So, get a better shell?

> The further from the rightmost position the part you want to edit is,
> the less convenient it is to do that editing, especially when doing
> multiple trial-and-error passes to figure out what syntax will actually
> produce the desired result.
> 
Again, it sounds like a better shell is in order.

> One item to the right of the final command (either redirection to a
> file, or pipe to a pager) is usually unavoidable, at least with output
> of any noticeable size; depending on your shell, there may be
> keybindings for quick movement along the command line which reduce the
> inconvenience again.
> 

Here is an alternative that places the interesting commands as far to
the right as possible:

$  i=~/test.txt; o=~/other_test.txt; (sed 's/config=.*$/config=/g' | tr -d '=') 
<${i} >${o}
$  cat other_test.txt 
Test config
Test config
Test config

That minimizes the distance between the end of the processing command
pipeline and the end of the line.  You can add spaces before and/or
after ';', '(', and ')' to create more explicit word boundaries if you
like.

> But having to jump back several stages along the command line, and not
> even to a point which is at the edge of a 'word' according to what (at
> least) the keybindings I'm familiar with recognize, is IMO not worth the
> tradeoff vs. saving a single process per invocation.
> 
You'll notice that it's not about saving a process.  The better way
involves a subshell '()' which will create a new process.

> > $ cat ~/other_test.txt 
> > Test config
> > Test config
> > Test config
> > 
> > Now I can add pipe stages within the sub-shell to my hearts content
> > and I can even do other things like replace "<~/test.txt" with
> > "<$(some other command that queries a database)" so that the input
> > does not even need to come from a real file.
> 
> Isn't it just as easy to replace 'cat test.txt |' with 'some other
> command that queries a database |' ?
> 
It is just as easy.  However, 'cat' is not a value-added part of the
processing pipeline.  So, why have it at all?

> And that approach preserves the intuitiveness of having the input be
> specified at the start of the command line, and the output at the end,
> instead of the input and the output both being specified at the end.
> 
What is intuitive is not always right or best.  It is better to properly
learn the features and functions of the shell or other environment so
that proper separation can be made between business logic and supporting
structures.

If the command being worked on ends up in a script it is much easier to
make the better form I suggested readable and maintainable than it is
with the more 'intuitive' version.

Regards,

-Roberto
-- 
Roberto C. Sánchez

Reply via email to