Bash string split by delimiter constrained by number of characters

I want to split a long text separated by spaces through bash, but I fail. The command below splits into characters, but not delimiters.

echo "The quick fox jumped over the lazy dog" | fold -w 10
echo "The quick fox jumped over the lazy dog" | sed -e 's/.\{9\}/&\n/g'

It would be nice to have it for some user bash interaction.

Input syntax

format_text 10 "The quick fox jumped over the lazy dog"

Output:

The quick
fox jumped
over the
lazy dog

You must notice that the third line would cut "l" letter from "lazy" off if not for spacing spacing rule.

Update: The current result is good, There is some issue with the work slicer I cannot get by myself: it does not break words before the limit is transpassed.

#!/bin/bash
printHeader () { declare -i line_length=$3 # Upper and lower fences local upper_command="print \"$1\" *" local upper_fence="$(python -c "$upper_command $line_length")" local lower_command="print \"$2\" *" local lower_fence="$(python -c "$lower_command $line_length")" # Slice words by some chracter counter local regex_counter="s/(.{$line_length}) /\1\n/g" # Complete line with dots and a pipe local res="$line_length - length" local repeat_pattern='$(repeat res \".\"; echo)' local fill_command="{res=($res); printf \"%s%s|\n\", $0, $repeat_pattern}" echo "$upper_fence" sed -r "$regex_counter" <<< $4 echo "$lower_fence"
}
printHeader "#" "#" 10 "The quick fox jumped over the lazy dog"

Current output without final token:

##########
The quick fox
jumped over
the lazy dog
##########
5

1 Answer

sed -r 's/([^ .]+ [^ .]+) /\1\n/g' <<< "The quick fox jumped over the lazy dog"
The quick
fox jumped
over the
lazy dog

The character set [^ .]+ means one or more + characters of any kind . excluding the ^ whitespaces. So the capture group ([^ .]+ [^ .]+) matches for patterns as string string. The whole regular expression has an additional whitespace at the end ([^ .]+ [^ .]+) (it could be included in the capture group in order to preserve it).

With sed by using the substitute s command we replace the matched pattern by the content of the first capture group \1 and a new line character \n instead of the whitespace. By the flag g we repeat the command to the end of each line. The -r option activates the extended regular expressions.


Update - this is the actual answer:

sed -r 's/(.{8}) /\1\n/g' <<< "How do we know it is going to match the pre-defined number of characters?"
How do we
know it is
going to
match the
pre-defined
number of
characters?

In this example we capture strings with length at least 8 characters (including whitespaces) followed by a whitespace. We can check the actual length of the output lines in a way as this:

sed -r 's/(.{8}) /\1\n/g' <<< "How do we know it is going to match the pre-defined number of characters?" \ | awk '{print length}'
9
10
8
9
11
9
11

And by the help of the answers of the question How to use printf to print a character multiple times? [awk] we can achieve the desired result.

sed -r 's/(.{8}) /\1\n/g' <<< "How do we know it is going to match the pre-defined number of characters?" \ | awk '{rest=(12 - length); printf "%s%s|\n", $0, substr(".........", 1, rest)}'
How do we...|
know it is..|
going to....|
match the...|
pre-defined.|
number of...|
characters?.|

In case you want to break the words remove the final whitespace from the above regular expression /(.{8})/. Here is an example where the max line length will be exactly 10 characters or less, where the second sed command will trim the whitespaces around each new line.

sed -r 's/(.{10})/\1\n/g' <<< "How do we know it is going to match the pre-defined number of characters?" \ | sed -r 's/(^ | $)//g' \ | awk '{rest=(10 - length); printf "%s%s|\n", $0, substr(".........", 1, rest)}'
How do we.|
know it is|
going to..|
match the.|
pre-define|
d number o|
f characte|
rs?.......|
15

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like