Bash - считать новые строки с помощью команды терминала - PullRequest
0 голосов
/ 29 октября 2018

Я пытаюсь создать bash-скрипт, который считает перевод строки во входных данных. Первый оператор if (switch $ 0) работает нормально, но проблема в том, что я пытаюсь заставить его прочитать WC файла в терминальном аргументе.

например. ~ $ ./script.sh

1

2

3

4

(пользователь нажимает CTRL + D)

показать количество слов здесь # ответ 5 - отлично работает

например. ~ $ .script1.sh

WC здесь - (5)

~ $ успешно перенаправляет стандартный ввод из файла

но например ~ $ ./script1.sh script1.sh script2.sh

WC отображается здесь для script1.sh

WC отображается здесь для script2.sh

НИЧЕГО

~ $

проблема, на мой взгляд, является вторым оператором if, вместо того, чтобы выполнить скрипт в терминале, он переходит к оператору if и ожидает ввода пользователя и не возвращает оператор echo.

Любая помощь будет принята с благодарностью, поскольку я не могу понять, почему она не будет работать без оператора ~ $ <. </p>

#!/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

Ответы [ 2 ]

0 голосов
/ 30 октября 2018
#!/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 существуют только в фигурных скобках, поскольку оболочка (в любом случае некоторые оболочки) использует подоболочки для команд в конвейере. Как правило, решение для этого заключается в перенаправлении из процесса замены (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 x против read x < <(cmd)

$ x=foo; echo bar | read x; echo $x
foo
$ x=foo; read x < <(echo bar); echo $x
bar
0 голосов
/ 29 октября 2018

Использование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...