简体   繁体   中英

Insert newline character at index in .bash

I'm taking an introductory course to bash at my university and am working on a little MotD script that uses a json-object grabbed from an API using curl.

I want to make absolutely certain that you understand that this is NOT an assignment, but something I'm playing around with to learn more about how to script with bash.

I've found myself stuck with what could possibly be a very simply issue; I want to insert a new line (' \\n ') on a specific index if the 'quote' value of my json-object is too long (in this case on index 80).

I've been following a bunch of SO threads and this is my current solution:

#!/bin/bash

json_object=$(curl -s 'http://quotes.stormconsultancy.co.uk/random.json')
quote=$(echo ${json_object} | jq .quote | sed -e 's/^"//' -e 's/"$//')
author=$(echo ${json_object} | jq .author)
count=${#quote}
echo $quote
echo $author
echo "wc: $count"


if((count > 80));
then
        quote=${quote:0:80}\n${quote:80:(count - 80)}
else
        echo "lower"
fi
printf "$quote"

The current output I receive from the printf is the first word of the quote, whereas if I have an echo before trying to do the string-manipulation I get the entire quote.

I'm sorry if it's not following best practice or anything, but I'm an absolute beginner using both vi and bash .

I'd be very happy with any sort of advice. :)

EDIT:

Sample output:

$ ./json.bash

You should name a variable using the same care with which you name a first-born child.

"James O. Coplien"

86

higher

You should name a variable using the same care with which you name a first-born nchild.

You can just use a single line bash command to achieve this,

string="You should name a variable using the same care with which you name a first-born child."
(( "${#string}" > 80 )) && printf "%s\n" "${string:0:80}"$'\n'"${string:80}" || printf "%s\n" "$string"
You should name a variable using the same care with which you name a first-born 
child.

(and) for an input line less than 80 charaacters

string="You should name a variable using the same care"
(( "${#string}" > 80 )) && printf "%s\n" "${string:0:80}"$'\n'"${string:80}" || printf "%s\n" "$string"
You should name a variable using the same care

An explanation,

(( "${#string}" > 80 )) && printf "%s\n" "${string:0:80}"$'\n'"${string:80}" || printf "%s\n" "$string"

# The syntax is a indirect implementation of ternary operator as bash doesn't 
# directly support it.
#
# (( "${#string}" > 80 )) will return a success/fail depending upon the length
# of the string variable and if it is greater than 80, the command after && is
# executed and if it fails the command after || is executed
#
# "${string:0:80}"$'\n'"${string:80}"
# A parameter expansion syntax for sub-string extraction.
#
# ${PARAMETER:OFFSET}
#
# ${PARAMETER:OFFSET:LENGTH}
#
# This one can expand only a part of a parameter's value, given a position 
# to start and maybe a length. If LENGTH is omitted, the parameter will be 
# expanded up to the end of the string. If LENGTH is negative, it's taken as
# a second offset into the string, counting from the end of the string.
#
# So in our example we basically extract the characters from position 0 to 80
# insert a new-line and append the rest of the string 
#
# The $'\n' syntax allows to include all escape sequence characters be 
# included, in this case just the new line character.

Not really in the original question, but adding some extra code to @Inian great answer to allow not to break in the middle of a word, but rather at the last white space in ${string:0:80} :

#!/usr/bin/env bash

string="You should really name a variable using the same care with which you name a first-born child."
if (( "${#string}" > 80 )); then
    maxstring="${string:0:80}"
    lastspace="${maxstring##*\ }"
    breakat="$((${#maxstring} - ${#lastspace}))"
    printf "%s\n" $"${string:0:${breakat}}"$'\n'"${string:${breakat}}"
else
    printf "%s\n" "$string"
fi

maxstring=${string:0:80} :

Let's get the first 80 characters of the quote.

lastspace=${maxstring##*\\ } :

Deletes longest match of *\\ (white space is escaped) from front of $maxstring , ${lastspace} will be the remaining string from last white space until end of the string.

breakat="$((${#maxstring} - ${#lastspace}))" :

Subtract the length of ${lastspace} with the length of ${maxstring} to get the last index of the white space from ${maxstring} . This is the index where \\n will be inserted.

Example output with "hard" break at character 80:

You should really name a variable using the same care with which you name a firs
t-born child.

Example output with a "soft" break at the closest white space from character 80:

You should really name a variable using the same care with which you name a 
first-born child.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM