2016-10-04 103 views
0

如何在Bash中的分隔符上分割字符串基础?在bash中的分隔符上分割一个字符串?

我有存储在变量中的字符串,如下所示:

DATA="111111-777777-Hello" 

现在我想在两个不同的变量来分割上述串上-定界符并存储两个数字。

NUMBER1="111111" 
NUMBER2="777777" 

如果NUMBER1和NUMBER2是一个空字符串,而不是一个号码,然后退出了与非零状态代码的脚本。

+1

在shell中为你自己的变量使用全部大写的名字是不好的形式。请参阅http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html - 所有大写名称用于具有操作系统和shell本身意义的环境变量(设置具有相同名称的shell变量即使没有任何尝试“导出”它也会覆盖一个类似命名的环境变量)。避开那个命名空间避免重写意外重要的东西。 –

+0

顺便说一句,既然你有这个标记的bash,我给了一个在bash中有效的答案 - 如果你想要一个与'#!/ bin/sh' shebang一起工作的东西,或者当以'sh yourscript'而不是'bash yourscript ',那会有所不同。 –

+0

感谢您对所有大写字母的建议。将研究这一点。是的,bash是我需要的。 – user1950349

回答

3
IFS=- read -r number1 number2 _ <<<"$DATA" 
[[ $number1 && $number2 ]] || { echo "Initial columns not read" >&2; exit 1; } 
[[ $number1$number2 = *[![:digit:]]* ]] && { echo "Values are not numeric" >&2; exit 1; } 

echo "Number 1 is $number1" 
echo "Number 2 is $number2" 

设置IFS到您的分隔符在同一行read命令(不带分隔符如;之间),它的作用域到单read操作,这样就不会在其他地方修改shell的行为在脚本中。

注意_作为read的额外参数 - 该行的其余部分存储在那里,防止它被附加到number2

+0

谢谢我们如何检查它们是否只是数字而不是空字符串,然后根据非零状态代码退出脚本? – user1950349

+0

修改为演示相同。 –

+0

...也修改为检查任何非数字数字。 –

0

,如果你想将它分割成一个阵列使用

split() { 
    # split string separator 
    # split a string into an array 
    # the array returned will be newArray 
    # on error return status is 1 
    # usage:- split bash?ksh?zsh?dash ? >>> returns an array of 3 elements bash[0] ksh[1] zsh[2] dash[3] 
    local string="${1}" separator="${2}" 
    declare cutOneCharacter; 
    declare tempvar 
    # appending $sepeartor to the ending of $string 
    # bacon?tuna?hamburger ? >>>>> if not appeneded the result will be>>>>>> bacon tuna //o_O where is hamburger ? 
    # if appeneded the result will be >>>> bacon tuna harmburger 
    string="$string$separator" 
    [[ ${newArray[@]} ]] && unset newArray 
    splitUsage() { 
    echo "Usage: split string separator" >&2 
    } 

    (("${#@}" != "2")) && splitUsage && return 1; 
    while [ -n "${string}" ];do 
    cutOneCharacter=$(printf "%c" "$string") 
    if [[ "${cutOneCharacter}" == "${separator}" ]];then 
     newArray+=("${tempvar}") 
     unset tempvar; 
    else 
     tempvar+="${cutOneCharacter}" 
    fi 
    string=${string#*?} 
    done 
    echo"${newArray[@]}" 
    return 0; 
} 

more details are here

+0

这个实现增加了什么值,而不是split(){IFS =“$ 2”read -r -a newArray <<<“$ 1”; }'? –

0

使用bash,操纵IFS

data="111111-777777-Hello" 
mapfile -t data < <(IFS=-; printf "%s\n" $data) # variable is not quoted 
echo "${data[0]}" # 111111 
echo "${data[1]}" # 777777 

不要使用全大写变量名 - 让他们保留给shell。

+0

只要阅读Charles Duffy的回答:比我的方式更好。 –

+1

我建议在扩展'$ data'之前关闭子shell中的globbing,以保证安全。 (如果'nullglob'被设置,'Hello'部分包含'[]'s,'''',&c。,可能会使整个扩展结果为空)。 –