how to pipe the stdout of one command into %- to remove the trailing dash in bash?

I have this command:

MODIFIED_BRANCH_NAME=$(echo $BRANCH_NAME | tr '/_.' '-' | tr -s '-' | tr '[:upper:]' '[:lower:]' )
MODIFIED_BRANCH_NAME=${MODIFIED_BRANCH_NAME%-}

I want to do it one line. how can I pipe something into %- operator?

example input:

abc//kdkd_kdkd_-  

expected:

abc-kdkd-kdkd

actually what I want to do is that after doing $(echo $BRANCH_NAME | tr '/_.' '-' | tr -s '-' | tr '[:upper:]' '[:lower:]' ) I want to remove the trailing “-” if existing

  • 1

    Any chance to have the raw output of echo $branch_name ?

    – 

  • @GillesQuénot do you mean an example? I added to the question

    – 

  • 3

    “how can I pipe something into %- operator” — %- is not an operator, it’s a parameter expansion mechanism. You need to have a parameter to expand.

    – 




  • 1

    “I want it on one line”, …. you can join the 2 lines and separate the cmds with ;, ie. MODIFIED_BRANCH_NAME=$(echo $BRA .... ) ; MODIFIED_BRANCH_NAME=${MODIFIED_BRANCH_NAME%-} . Good luck.

    – 

  • 1

    Why do you want to use %- for this part when you’ve used 3 pipes and 3 calls to tr for the rest of it? WHAT you’re asking to do, I want to remove the trailing "-" if existing, is trivial but HOW you’re asking to do it, how can I pipe something into %-, is impossible.

    – 




how can I pipe something into %- operator?

you can’t pipe something into an operator. An operator works on a value, not a stream.

remove the trailing dash in bash?

sed would be an easy way. sed 's/-$//g' will replace a - ad the end ($). Demo:

% sed s/-$//g <<<"hi-world-"
hi-world

So your new pipeline might look like:

MODIFIED_BRANCH_NAME=$(echo $BRANCH_NAME | tr '/_.' '-' | tr -s '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//g' )

Or you could replace those commands with sed which can do most of them.

%# echo "Ji/wor..ld_" | sed -e s/[./_]/-/g -e 's/-\{2,\}/-/g' -e s/-$//g   | tr [:upper:] [:lower:]
ji-wor-ld

All this can be done in one single gnu-sed command like this:

branch_name="abc//kdkd_kdKD_-"

sed -E 's#[/_.-]+#-#g; s/-$//; s/[A-Z]+/\L&/g' <<< "$branch_name"

abc-kdkd-kdkd

Here is the breakup:

  • s#[/_.-]+#-#g: Replaces 1+ of / or _ or . or - by a single -
  • s/-$//: Removes trailing -
  • s/[A-Z]+/\L&/g: Lowercase all uppercase substrings

You can do this using only Bash built-ins. It’s commonplace to find scripts that don’t use fancy sed or awk regexes to modify strings that use Bash’s string manipulation on a line-by-line basis. It’s more verbose but it’s arguably easier to reason about and debug.

shopt -s extglob
MODIFIED_BRANCH_NAME=${BRANCH_NAME//['/_.']/-}         # translate illegal characters
MODIFIED_BRANCH_NAME=${MODIFIED_BRANCH_NAME//+(-)/-}   # collapse repeating -
MODIFIED_BRANCH_NAME=${MODIFIED_BRANCH_NAME,,}         # lower-case
MODIFIED_BRANCH_NAME=${MODIFIED_BRANCH_NAME%-}         # trim trailing -

However, if your goal for this script is to minimize lines of shell, then you can a sed:

MODIFIED_BRANCH_NAME=$(echo $BRANCH_NAME |
    tr '/_.' '-' |                # translate illegal characters
    tr -s '-' |                   # collapse repeating -
    tr '[:upper:]' '[:lower:]' |  # lower-case
    sed -e 's,-$,,'               # trim trailing -
)

What I would do in one pass with awk:

echo "$branch_name" | awk -F '[-_/]' '{OFS="-"}{$0=tolower($0);print $1,$3,$4}'
abc-kdkd-kdkd

Leave a Comment