【问题标题】:Bash- Count Newlines via terminal commandBash- 通过终端命令计算换行符
【发布时间】:2018-10-29 20:13:29
【问题描述】:

我正在尝试制作一个 bash 脚本来计算输入中的换行符。第一个 if 语句(switch $0)工作正常,但我遇到的问题是试图让它读取终端参数中文件的 WC。

例如 ~$ ./script.sh

1

2

3

4

(用户按下 CTRL+D)

在此处显示字数 # 答案为 5 - 工作正常

例如 ~$ .script1.sh

这里是厕所-(5)

~$ 成功从文件重定向标准输入

但是 例如 ~$ ./script1.sh script1.sh script2.sh

此处为 script1.sh 显示 WC

此处为 script2.sh 显示 WC

没什么

~$

我认为的问题是第二个 if 语句,而不是在终端中执行脚本,而是转到 if 语句并等待用户输入并且它没有返回 echo 语句。

任何帮助将不胜感激,因为我无法弄清楚为什么没有 ~$

#!/bin/bash
#!/bin/sh

read filename ## read provided filename
USAGE="Usage: $0 $1 $2..." ## switch statement

if [ "$#" == "0" ]; then  
    declare -i lines=0 words=0 chars=0
    while IFS= read -r line; do
    ((lines++))
    array=($line)               
    ((words += ${#array[@]}))
    ((chars += ${#line} + 1))   # add 1 for the newline
done < /dev/stdin
fi
echo "$lines $words $chars $filename" ## filename doesn't print, just filler

### problem if statement####
if [ "$#" != "0" ]; then # space between [] IS VERY IMPORTANT
    declare -i lines=0 words=0 chars=0
    while IFS= read -r line; do
    lines=$( grep -c '\n'<"filename") ##should use grep -c to compare only new lines in the filename. assign to variable line
    words=$( grep -c '\n'<"filename")
    chars=$( grep -c '\n'<"filename")
echo "$lines $words $chars"
 #lets user press CTRL+D to end script and count the WC
fi

【问题讨论】:

  • 在变量赋值中,= 周围不能有空格。
  • 啊,谢谢!我会在上面修复它。

标签: linux bash macos shell


【解决方案1】:
#!/bin/sh
set -e
if [ -t 0 ]; then
    # We are *not* reading stdin from a pipe or a redirection.
    # Get the counts from the files specified on the cmdline
    if [ "$#" -eq 0 ]; then
        echo "no files specified" >&2
        exit 1
    fi
    cat "$@" | wc
else
    # stdin is attached to a pipe or redirected from a file
    wc
fi | { read lines words chars; echo "lines=$lines words=$words chars=$chars"; }

read 命令中的变量仅存在于大括号中,这是由于 shell(无论如何是某些 shell)使用子shell 来执行管道中的命令的方式。通常,解决方案是从进程替换 (bash/ksh) 重定向。

这可以压缩成

#!/bin/bash
[[ -t 0 ]] && files=true || files=false
read lines words chars < <({ ! $files && cat || cat "$@"; } | wc) 
echo "lines=$lines words=$words chars=$chars"

cmd | read xread x &lt; &lt;(cmd) 的快速演示

$ x=foo; echo bar | read x; echo $x
foo
$ x=foo; read x < <(echo bar); echo $x
bar

【讨论】:

  • 我不知道读取变量,谢谢你解释它现在有意义。你的代码看起来很棒!我希望有一天能像你的压缩版本一样制作高效的代码。
  • 只是为了强调这一点......read x &lt;&lt;&lt; $(if :; then echo x; fi) 有效(如前所述,进程替换)。 var read 创建的变量是作用域的;管道创建作用域子shell,所以echo bar|read foo; echo $foo 让$foo 在read 的末尾消失,然后echo 执行,并且没有打印任何内容。 echo bar| { read foo; echo $foo; } 使用大括号将echo $foo 保持在read foo 的范围内。希望对某人有所帮助。不过,格伦是完全正确的。 ;)
【解决方案2】:

使用wc

也许最简单的方法是将第二个if 块替换为for

$: cat tst
#! /bin/env bash
declare -i lines=0 words=0 chars=0
case "$#" in
0)  wc ;;
*)  for file in $*
    do  read lines words chars x <<< "$( wc $file )"
        echo "$lines $words $chars $file"
    done ;;
esac
$: cat foo

hello
world
and
goodbye cruel world!

$: tst < foo
 6  6 40
$: tst foo tst
6 6 40 foo
9 38 206 tst

【讨论】:

  • 看起来很棒!谢谢。
猜你喜欢
  • 1970-01-01
  • 2015-06-23
  • 2016-02-10
  • 2011-10-31
  • 2011-07-01
  • 2020-09-07
  • 2017-01-25
  • 1970-01-01
  • 2018-01-11
相关资源
最近更新 更多