削减unix变量

时间:2014-08-12 09:59:33

标签: bash unix cut

我现在有以下内容:

for file in *
  do
  list="$list""$file "`cat $file | wc -l | sort -k1`$'\n'
  done

echo "$list"

这是打印:

fileA 10
fileB 20
fileC 30

然后我想循环浏览$listcut第2列并执行计算。

当我这样做时:

for line in "$list"
  do
     noOfLinesInFile=`echo "$line" | cut -d\  -f2`
     echo "$noOfLinesInFile"
  done

打印:

10
20
30

但是for loop只输入一次。在此示例中,它应该输入loop 3次。

有人可以告诉我在这里应该做些什么来实现这个目标吗?

4 个答案:

答案 0 :(得分:1)

如果引用变量

for line in "$list"

只有一个单词,所以循环只执行一次。

如果没有引号,$line将会填充$list中找到的任何单词,这也不是您想要的单词,因为它会逐个处理值,而不是行。

您可以将$IFS变量设置为换行符,以便在换行符上拆分$list

IFS=$'\n'
for line in $list ; do
   ...
done

不要忘记将IFS重置为原始值 - 要么将整个部分放入子shell中(如果没有变量应该在循环中存活)

(
  IFS=$'\n'
  for ...
)

或备份值:

IFS_=$IFS
IFS=$'\n'
for ...
    IFS=$IFS_
    ...
done

答案 1 :(得分:0)

这是因为shell中的列表只是使用空格作为分隔符来定义。

# list="a b c"
# for i in $list; do echo $i; done
a
b
c
# for i in "$list"; do echo $i; done
a b c

在你的第一个循环中,你实际上并没有在shell sens中建立一个列表。 您应该为循环,附加或剪切设置默认分隔符以外的其他分隔符。

答案 2 :(得分:0)

改为使用数组:

#!/bin/bash

files=()
linecounts=()

for file in *; do
    files+=("$file")
    linecounts+=("$(wc -l < "$file")")
done

for i in "${!files[@]}" ;do
    echo "${linecounts[i]}"
    printf '%s %s\n' "${files[i]}" "${linecounts[i]}"  ## Another form.
done

虽然可以更简单地完成printf '%s\n' "${linecounts[@]}"

答案 3 :(得分:0)

wc -l只输出一个值,因此您无需对其进行排序:

for file in *; do
    list+="$file "$( wc -l < "$file" )$'\n'
done
echo "$list"

然后,您可以使用while循环逐行读取列表:

while read file nlines; do
    echo $nlines
done <<< "$list"

如果任何文件名都有空格,那么while循环是脆弱的。这有点强大:

while read -a words; do
    echo ${words[-1]}
done <<< "$list"