How to convert a string to lower case in Bash?

前端 未结 20 2249
慢半拍i
慢半拍i 2020-11-22 09:40

Is there a way in bash to convert a string into a lower case string?

For example, if I have:

a=\"Hi all\"

I want to convert it to:<

20条回答
  •  轮回少年
    2020-11-22 09:58

    This is a far faster variation of JaredTS486's approach that uses native Bash capabilities (including Bash versions <4.0) to optimize his approach.

    I've timed 1,000 iterations of this approach for a small string (25 characters) and a larger string (445 characters), both for lowercase and uppercase conversions. Since the test strings are predominantly lowercase, conversions to lowercase are generally faster than to uppercase.

    I've compared my approach with several other answers on this page that are compatible with Bash 3.2. My approach is far more performant than most approaches documented here, and is even faster than tr in several cases.

    Here are the timing results for 1,000 iterations of 25 characters:

    • 0.46s for my approach to lowercase; 0.96s for uppercase
    • 1.16s for Orwellophile's approach to lowercase; 1.59s for uppercase
    • 3.67s for tr to lowercase; 3.81s for uppercase
    • 11.12s for ghostdog74's approach to lowercase; 31.41s for uppercase
    • 26.25s for technosaurus' approach to lowercase; 26.21s for uppercase
    • 25.06s for JaredTS486's approach to lowercase; 27.04s for uppercase

    Timing results for 1,000 iterations of 445 characters (consisting of the poem "The Robin" by Witter Bynner):

    • 2s for my approach to lowercase; 12s for uppercase
    • 4s for tr to lowercase; 4s for uppercase
    • 20s for Orwellophile's approach to lowercase; 29s for uppercase
    • 75s for ghostdog74's approach to lowercase; 669s for uppercase. It's interesting to note how dramatic the performance difference is between a test with predominant matches vs. a test with predominant misses
    • 467s for technosaurus' approach to lowercase; 449s for uppercase
    • 660s for JaredTS486's approach to lowercase; 660s for uppercase. It's interesting to note that this approach generated continuous page faults (memory swapping) in Bash

    Solution:

    #!/bin/bash
    set -e
    set -u
    
    declare LCS="abcdefghijklmnopqrstuvwxyz"
    declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    
    function lcase()
    {
      local TARGET="${1-}"
      local UCHAR=''
      local UOFFSET=''
    
      while [[ "${TARGET}" =~ ([A-Z]) ]]
      do
        UCHAR="${BASH_REMATCH[1]}"
        UOFFSET="${UCS%%${UCHAR}*}"
        TARGET="${TARGET//${UCHAR}/${LCS:${#UOFFSET}:1}}"
      done
    
      echo -n "${TARGET}"
    }
    
    function ucase()
    {
      local TARGET="${1-}"
      local LCHAR=''
      local LOFFSET=''
    
      while [[ "${TARGET}" =~ ([a-z]) ]]
      do
        LCHAR="${BASH_REMATCH[1]}"
        LOFFSET="${LCS%%${LCHAR}*}"
        TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}"
      done
    
      echo -n "${TARGET}"
    }
    

    The approach is simple: while the input string has any remaining uppercase letters present, find the next one, and replace all instances of that letter with its lowercase variant. Repeat until all uppercase letters are replaced.

    Some performance characteristics of my solution:

    1. Uses only shell builtin utilities, which avoids the overhead of invoking external binary utilities in a new process
    2. Avoids sub-shells, which incur performance penalties
    3. Uses shell mechanisms that are compiled and optimized for performance, such as global string replacement within variables, variable suffix trimming, and regex searching and matching. These mechanisms are far faster than iterating manually through strings
    4. Loops only the number of times required by the count of unique matching characters to be converted. For example, converting a string that has three different uppercase characters to lowercase requires only 3 loop iterations. For the preconfigured ASCII alphabet, the maximum number of loop iterations is 26
    5. UCS and LCS can be augmented with additional characters

提交回复
热议问题