Я хочу создать скрипт для чтения файла .txt
. Это мой код:
while IFS= read -r lines
do
echo "$lines"
done < <(tail -n +2 filename.txt)
Я пробовал много вещей, таких как:
<<(tail -n +2 in.txt)
< < (tail -n +2 in.txt)
< (tail -n +2 in.txt)
<(tail -n +2 in.txt)
(tail -n +2 in.txt)
Я ожидал напечатать меня со второй строки, но вместо этого получаю сообщение об ошибке:
Syntax error: redirection unexpected
я знаю, что если я запущу его как bash, он будет работать, но я должен написать его в sh, есть ли способ?
смотри мой ответ ниже
Если вы не возражаете против подоболочки, вы можете использовать tail … | while …
.
Это не имеет ничего общего с tail
, и все, что связано с синтаксисом замены процесса.
Как говорится в этом ответе Оболочка POSIX эквивалентна <() вы можете использовать именованные каналы для имитации замены процесса в POSIX. Ваш скрипт будет выглядеть так:
#!/usr/bin/env sh
mkfifo foo.fifo
tail -n +2 filename.txt >foo.fifo &
while IFS= read -r lines
do
echo "$lines"
done < foo.fifo
rm foo.fifo
Как вы видите, что этот вопрос не является прямым дубликатом этого вопроса? Это не вызывает вопросов, связанных с tail
; это просто спрашивает то же самое (как использовать подстановку процесса в sh
) более расплывчато, без выполнения домашнего задания по знанию терминологии.
Теперь, когда вы говорите это, я также думаю, что это дубликат. Я не думал об этом как о дубликате, потому что OP даже не знает, почему его сценарий не работает, он не сказал, что у него проблемы с заменой процессов.
Если вы просто хотите проигнорировать первую строку, нет никакой веской причины использовать tail
вообще!
{
read -r first_line
while IFS= read -r line; do
printf '%s\n' "$line"
done
} <filename.txt
Использование read
для использования первой строки оставляет исходный указатель файла нетронутым, поэтому следующий код может читать непосредственно из файла, а не из FIFO, прикрепленного к выходным данным программы tail
; таким образом, это намного ниже накладных расходов.
Если вы сделал хотите использовать tail
, для конкретного поднятого случая вам не нужно использовать подстановку процесса (<(...)
), вы можете просто подключиться к вашему циклу while
. Обратите внимание, что это имеет серьезный побочный эффект, поскольку любые переменные, которые вы устанавливаете в цикле, больше не будут доступны после его выхода; это задокументировано (в кросс-оболочке) в БашFAQ #24.
tail -n +2 filename.txt | while IFS= read -r line
do
printf '%s\n' "$line"
done
Это сработает, если вы запустите его с
Bash
. Замена процесса не является функцией POSIX.