打印5的倍数的行号

时间:2014-05-14 07:13:28

标签: bash

您好我正在尝试打印/回显5的倍数的行号。我在shell脚本中这样做。我收到错误,无法继续。下面是脚本

#!/bin/bash
x=0
y=$wc -l $1
while [ $x -le $y ]
do
  sed -n `$x`p $1
  x=$(( $x + 5 ))
done

当执行上面的脚本时,我得到以下错误

#./echo5.sh sample.h
./echo5.sh: line 3: -l: command not found
./echo5.sh: line 4: [: 0: unary operator expected

请帮我解决这个问题。

5 个答案:

答案 0 :(得分:3)

为了提高效率,您不希望在文件上多次调用sed来选择特定的行。您想要阅读该文件一次,过滤掉您不想要的行。

#!/bin/bash
i=0
while IFS= read -r line; do
    (( ++i % 5 == 0 )) && echo "$line"
done < "$1"

演示:

$ i=0; while read line; do (( ++i % 5 == 0 )) && echo "$line"; done < <(seq 42)
5
10
15
20
25
30
35
40

答案 1 :(得分:2)

一个有趣的纯Bash可能性:

#!/bin/bash

mapfile ary < "$1"
printf "%.0s%.0s%.0s%.0s%s" "${ary[@]}"

这会将文件转换为数组ary,该数组位于数组字段中。然后printf负责每5行打印一次:%.0s占用一个字段,但什么都不做,%s打印字段。由于在没有mapfile选项的情况下使用-t,因此新行包含在数组中。当然,这确实会将文件丢入内存中,因此对于大文件来说可能并不好。对于大型文件,您可以使用mapfile回调:

#!/bin/bash

callback() {
    printf '%s' "$2"
    ary=()
}
mapfile -c 5 -C callback ary < "$1"

我们在回调期间删除了数组的所有元素,这样数组就不会变得太大,并且在读取文件时即时完成打印。


另一个有趣的可能性,在格伦杰克曼的解决方案的精神,但没有一个柜台(仍然纯粹的Bash):

#!/bin/bash

while read && read && read && read && IFS= read -r line; do
    printf '%s\n' "$line"
done < "$1"

答案 2 :(得分:1)

使用sed。

sed -n '0~5p' $1

这将从0开始打印文件中的每隔五行

另外

y=$wc -l $1

不会工作

y=$(wc -l < $1)

您需要创建一个子shell,因为bash会将空格视为赋值的结尾,如果您只想将该数字最佳地重定向到wc。

不知道你试图用这个做什么?

x=$(( $x + 5 ))

猜测你试图使用let,所以id建议查找该命令的语法。它看起来更像是

((x = x + 5))

希望这有帮助

答案 3 :(得分:0)

有更简洁的方法可以做到这一点,但你正在寻找的是这个。

#!/bin/bash
x=5
y=`wc -l $1`
y=`echo $y | cut -f1 -d\ `
while [ "$y" -gt "$x" ] 
do
  sed -n "${x}p" "$1"
  x=$(( $x + 5 ))
done

将x初始化为5,因为没有&#34;行0&#34;在你的文件$ 1。

此外,wc -l $ 1将显示行数,后跟文件名。使用cut来删除文件名并保留第一个单词。

在条件中,零值可以解释为&#34; true&#34;在巴什。

在sed命令中,$ x和p之间不应该有空格。你可以使用花括号将它们放在一起。

答案 4 :(得分:0)

你可以使用awk非常简洁地完成这个:

awk 'NR % 5 == 0' "$1"

NR是记录号(在这种情况下为行号)。每当它是5的倍数时,表达式为真,因此打印该行。

您可能也喜欢更短但可读性更低的内容:

awk '!(NR%5)' "$1"

做同样的事情。