1

How can this be done?

I don't see any applicable option in the manual.

I have positively checked that indentation breaks after ten million lines.

You can check it like:

$ (for i in `seq 0 10000000`; do echo "$i"; done) | nl

I don't often generate so many lines, but I don't want it to break like it does. How can this be done?

  • I doubt it is in nl that's the bottleneck. Counter-test: seq -s$'\n' 0 10000000 | nl (if your seq supports -s) – muru Jan 14 '15 at 10:59
  • @muru, that's just seq 0 10000000 | nl here. seq outputs numbers one per line. That's `...` soaking the seq output, that's what it's meant to do. – Stéphane Chazelas Jan 14 '15 at 13:13
  • @StéphaneChazelas I didn't remember seq's default separator, but the point remains that nl isn't to blame here. – muru Jan 14 '15 at 14:03
  • Well seq 0 10000000 | nl | head is a faster test case. Is this question really about the default width of the field reserved for space padding (right-alignment)? – orion Jan 14 '15 at 14:05
  • My nl version is not providing an option to soak up all standard input before writing its standard output. I'ld desire such an option. Do you know any workaround for such a not existing option? – uprego Jan 14 '15 at 14:40
4

If you are suggesting that nl should buffer the entire input simply to measure the maximum required number, that is not in the spirit of stream filters at all. With rare exceptions (sort, for instance), core utilities try to process streams immediately -- especially as they may be used in a virtually infinite pipeline (for instance, a loging stream that is incrementally filtered through nl and redirected into a file could accumulate quite a lot of data).

The standard way to handle padding is to simply specify the maximal expected width as a parameter. In this case, you can either turn off padding (I prefer this anyway, it makes sense to just have space separated column at the front), or set a different width. Compare:

seq 0 10000000 | nl -w12 # default right-justify, 12 character width

seq 0 10000000 | nl -w1 # default right-justify, 1 character width (no padding)

seq 0 10000000 | nl -w1 -s' ' # right-justify, space delimited instead of tab

seq 0 10000000 | nl -nln # left-justify

If you really want to do this automatically, just use wc -l to first measure the length and then set the -w appropriately.

1

The seq 0 10000000 is expanding to ten million and one lines, which bash needs to store in its memory so that it can loop over the values. That is what breaks, I managed to terminate it before it used up all the memory + swap on my system (I didn't want the out-of-memory to kill some other process, although modern kernels will correctly determine which process to kill).

You can check it's not nl by replacing nl with cat or wc or whatever other command that reads its input.

muru's version should be equivalent without requiring bash to store all that data intermediately.

EDIT: if it is about the number padding, I would have expected that a 10 second read of the manpage would have led to the nl -w option... Use nl -w8. If you're then unsatisfied with the large gap between line number and line contents (due to the default tab being used), you can add -s' '; it's all there in the manpage, easily found. I'm still wondering why the for loop in the question though.

  • 1
    I don't think this is what he asked. I think it's about the number padding. – orion Jan 14 '15 at 14:03
  • @orion is right. – uprego Jan 14 '15 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.