Я пытаюсь извлечь список дат из серии ссылок, используя функцию дампа lynx и передавая вывод через grep и awk. Эта операция успешно работает в терминале и точно выводит даты. Однако, когда он помещается в сценарий оболочки, bash сообщает о синтаксической ошибке:
Scripts/ETC/PreD.sh: line 18: syntax error near unexpected token `('
Scripts/ETC/PreD.sh: line 18: ` lynx --dump "$link" | grep -m 1 Date | awk '{print substr($0,10)}' >> dates.txt'
Для контекста, это часть цикла чтения, в котором $link читается из файла. Все операции, выполняемые в этом цикле, когда команда awk удалена, выполняются успешно, как и аналогичные циклы, включающие другие команды awk.
Я знаю, что либо я неправильно понимаю, как bash обрабатывает подстановку переменных, либо как bash обрабатывает команды awk, либо какое-то их сочетание. Любая помощь будет очень признательна.
Обновлено: Shellcheck разделен на это, версия веб-сайта не находит ошибок, но моя загруженная версия выдает ошибку SC1083, в которой говорится:
This { is literal. Check expression (missing ;/\n?) or quote it.
Проверка на странице Shellcheck GitHub дает следующее:
This error is harmless when the curly brackets are supposed to be literal, in e.g. awk {'print $1'}.
However, it's cleaner and less error prone to simply include them inside the quotes: awk '{print $1}'.
Сценарий следующий:
#!/bin/bash
while read -u 4 link
do
IFS=/ read a b c d e <<< "$link"
echo "$e" >> 1.txt
lynx --dump "$link" | grep -A 1 -e With: | tr -d [:cntrl:][:digit:][] | sed 's/\With//g' | awk '{print substr($0,10)}' | sed 's/\(.*\),/\1'\ and'/' | tr -s ' ' >> 2.txt
lynx --dump "$link" | grep -m 1 Date | awk '{print substr($0,10)}' >> dates.txt
done 4< links.txt
Вам нужно опубликовать сценарий, если вы хотите помочь в его отладке.
Что вы пытаетесь сделать с tr -d [:cntrl:][:digit:][]
(особенно с []
в конце и без кавычек вокруг сценария)? Что вы пытаетесь сделать с sed 's/\(.*\),/\1'\ and'/'
? Опубликуйте ПОЛНЫЙ минимальный скрипт, который выдает сообщение об ошибке — мы даже не видим шебанга в опубликованном вами фрагменте.
Какую оболочку вы использовали в шелчеке? Вы использовали правильный Шебанг?
Проблема может быть в любой из 3-х программ длинной трубы. Обратите внимание, что переменная length
в скрипте awk
всегда равна 0.
Сообщение об ошибке shellcheck, которое вы публикуете, похоже, не из кода, который вы опубликовали.
@DudiBoy, к сожалению, POSIX позволяет вызывать функцию length()
не только без аргументов, но даже без скобок, поэтому вы можете написать length
, и это означает то же, что и length($0)
. Ужасно, и лично я никогда бы этого не сделал, но мы застряли с этим. В коде OP вообще нет смысла присутствовать в этом substr($0,10,length)
, так как это будет большее значение, которое может присутствовать после начального индекса 10 - substr($0,10)
более лаконичен и семантически лучше.
Код, указанный здесь, имеет проблемы, но не должен вызывать указанную ошибку. Я предполагаю, что ранее в сценарии была проблема с цитированием (в одной из 12 пропущенных строк перед цитируемым разделом), которая вызывает проблему синтаксического анализа цепочки.
В команде sed
у вас есть непревзойденный '
из-за некавычек '
.
В скрипте awk
у вас есть постоянная нулевая переменная length
.
Из руководство по тарабарщине:
substr(string, start [, length ])
Return a length-character-long substring of string, starting at character number start. The first character of a string is character number one.48 For example, substr("washington", 5, 3) returns "ing".
If length is not present, substr() returns the whole suffix of string that begins at character number start. For example, substr("washington", 5) returns "ington". The whole suffix is also returned if length is greater than the number of characters remaining in the string, counting from character start.
If start is less than one, substr() treats it as if it was one. (POSIX doesn’t specify what to do in this case: BWK awk acts this way, and therefore gawk does too.) If start is greater than the number of characters in the string, substr() returns the null string. Similarly, if length is present but less than or equal to zero, the null string is returned.
Также я предлагаю вам объединить grep|awk|sed|tr
в один скрипт awk. И отладьте awk-скрипт с распечатками.
От:
lynx --dump "$link" | grep -A 1 -e With: | tr -d [:cntrl:][:digit:][] | sed 's/\With//g' | awk '{print substr($0,10,length)}' | sed 's/\(.*\),/\1'\ and'/' | tr -s ' ' >> 2.txt
К:
lynx --dump "$link" | awk '/With/{found=1;next}found{found=0;print sub(/\(.*\),/,"& and",gsub(/ +/," ",substr($0,10)))}' >> 2.txt
От:
lynx --dump "$link" | grep -m 1 Date | awk '{print substr($0,10,length)}' >> dates.txt
К:
lynx --dump "$link" | awk '/Date/{print substr($0,10)}' >> dates.txt
похоже, ошибка не в
awk
, вы должны поместить свой скрипт в shellcheck.net, чтобы получить синтаксическую ошибку. Кроме того, использованиеgrep
иawk
в одной строке излишне,