Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
循环使用逗号分隔的shell变量_Shell_Loops_Unix_For Loop_Cut - Fatal编程技术网

循环使用逗号分隔的shell变量

循环使用逗号分隔的shell变量,shell,loops,unix,for-loop,cut,Shell,Loops,Unix,For Loop,Cut,假设我有一个unixshell变量,如下所示 variable=abc,def,ghij 我想使用for循环提取所有值(abc、def和ghij),并将每个值传递到一个过程中 该脚本应允许从$variable提取任意数量的逗号分隔值。请尝试此脚本 #/bin/bash testpid="abc,def,ghij" count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way count=`expr $count

假设我有一个unixshell变量,如下所示

variable=abc,def,ghij
我想使用for循环提取所有值(
abc
def
ghij
),并将每个值传递到一个过程中

该脚本应允许从
$variable

提取任意数量的逗号分隔值。请尝试此脚本

#/bin/bash   
testpid="abc,def,ghij" 
count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way
count=`expr $count + 1` 
while [ $count -gt 0 ]  ; do
     echo $testpid | cut -d ',' -f $i
     count=`expr $count - 1 `
done

您可以使用下面的脚本动态遍历变量,不管它有多少个字段,只要它是逗号分隔的

variable=abc,def,ghij
for i in $(echo $variable | sed "s/,/ /g")
do
    # call your procedure/other scripts here below
    echo "$i"
done
在for循环内的
do
done
之间,您可以调用过程
proc“$i”
,而不是上面的
echo“$i”
调用


更新:如果变量的值不包含空格,则上述代码段有效。如果您有这样的要求,请使用可以更改
IFS
的解决方案之一,然后解析您的变量



希望这有帮助。

如果设置了不同的字段分隔符,可以直接使用
for
循环:

IFS=","
for v in $variable
do
   # things with "$v" ...
done
您还可以将值存储在数组中,然后按如下所示在其中循环:

您可以在这个解决方案中找到更广泛的方法来解决问题

关于第二种方法的例子:

$ IFS=, read -ra vals <<< "abc,def,ghij"
$ printf "%s\n" "${vals[@]}"
abc
def
ghij
$ for v in "${vals[@]}"; do echo "$v --"; done
abc --
def --
ghij --
$IFS=,read-ra vals不干扰IFS
不调用外部命令

variable=abc,def,ghij
for i in ${variable//,/ }
do
    # call your procedure/other scripts here below
    echo "$i"
done
使用bash字符串操作

我更喜欢使用tr而不是sed,因为sed在某些情况下与特殊字符\r\n有关


另一种解决方案是将IFS设置为某个分隔符

另一种不使用IFS但仍保留空格的解决方案:

$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij
$var=“a bc、def、ghij”

$whilereadline;do echo line=“$line”;完成<这里有一个替代的基于tr的解决方案,不使用echo,表示为一行

for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done

对于$(tr')中的v,''\n'这是我的纯bash解决方案,它不改变IFS,并且可以接受自定义正则表达式分隔符

loop_custom_delimited() {
    local list=$1
    local delimiter=$2
    local item
    if [[ $delimiter != ' ' ]]; then
        list=$(echo $list | sed 's/ /'`echo -e "\010"`'/g' | sed -E "s/$delimiter/ /g")
    fi
    for item in $list; do
        item=$(echo $item | sed 's/'`echo -e "\010"`'/ /g')
        echo "$item"
    done
}


通过迭代你到底想做什么?我想通过每个字段(比如abc)作为过程的参数。但如果我不确定变量testpid中的字段数量,该怎么办?此外,我需要将上述变量的每个字段作为参数传递给过程。我希望这样做,直到变量的长度变为零。(即,所有字段都应传递一次给过程进行处理)我不知道这个过程。从这个链接可以得到字段的计数。
http://stackoverflow.com/questions/8629330/unix-count-of-columns-in-file
。之后,将for循环转换为while循环。您可以获得该循环。我猜这是从文件中计算字段。如果我需要计算变量中的字段,该怎么办(假设变量为testpid=abc,def,ghij)回显变量并将输出传输到awk。或者查看我更新的答案。可能有用。另请参阅:-)祝大家好运。是的!我也想到了这一点,只是它需要执行以下步骤:a
while
读入数组,另一个读取结果。当有人真正知道如何使用shell,而不是将一堆binutil组合在一起时,这让我很高兴。你必须将
IFS
设置回之前的状态吗re?@fedorqui它做到了!这是我想循环使用的唯一变量,它使我的yaml文件更易于读取(而不是一个长的环境变量,它有一堆行)。如果
$variable
包含空格,则这不起作用,例如
variable=ab,c,d
=>打印4行(a | b | c | d),而不是3行(a | b | c | d)此外,它还添加了新的引号,如**
“value
**。如果有任何正则表达式可以删除,请更新。好的方面是可以使用不同的分隔符嵌套多个循环。好的建议!避免与
IFS
混淆的好提示!小警告-如果
$i
中的任何值包含空格,它们将被拆分。”(这可能是它以逗号分隔而不是空格分隔的形式传递的原因)如果以前的函数更改了IFS设置,那么这不起作用…将其更改为:
对于${variable/,/$IFS}do中的i;echo“$i”;done
我收到错误消息“Bad substitution”当我尝试这种方法时,它在bash中正常工作,但是zsh会吞噬空间。
$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij
for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done
loop_custom_delimited() {
    local list=$1
    local delimiter=$2
    local item
    if [[ $delimiter != ' ' ]]; then
        list=$(echo $list | sed 's/ /'`echo -e "\010"`'/g' | sed -E "s/$delimiter/ /g")
    fi
    for item in $list; do
        item=$(echo $item | sed 's/'`echo -e "\010"`'/ /g')
        echo "$item"
    done
}