您好我正在尝试打印/回显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
请帮我解决这个问题。
答案 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"
做同样的事情。