С awk
:
awk -F"\t" '$1!=""&&$2!=""&&$3!=""' file
На самом деле все просто.
awk
разделяет ввод на табуляции разделителя полей \t
, заданного флагом -F
. Этот флаг может быть опущен, если в вашем контенте нет пробелов в полях. $1!=""&&...
- это условие. Когда это условие истинно, awk
просто печатает строку. Вы также можете написать '$1!=""&&$2!=""&&$3!=""{print}'
, но это не обязательно. Поведение Awks по умолчанию заключается в печати строки, если не задано никакого действия. Здесь это условие верно, когда поля $1
, $2
и $3
не пусты, следовательно, когда первые три поля имеют значение. Для записи в другой файл используйте следующее:
awk -F"\t" '$1!=""&&$2!=""&&$3!=""' input_file >output_file
Edit: awk
, он проверяет каждое поле в строке:
awk -F"\t" '{for(i=1;i<=NF;i++){if($i==""){next}}}1' file
У вас есть синтаксические и логические ошибки.
$a=true
— это просто строка, а НЕ операция сравнения. Разделяйте пробелами, чтобы происходило сравнение:"$a" = true
.
При такой работе петля вообще не будет введена, так как вы установили a=false
заранее.
ЕСЛИ вы, наконец, войдете в цикл, вы не сможете выйти, так как a
никогда не устанавливается ни на что, кроме true
, и не используется другой механизм выхода (, например.break
)предусмотрено.
Попробуйте использовать просто break, чтобы остановить бесконечный цикл, подобный этому:
echo "$(tput setaf 4) Tell me where the file is:"
echo # This prints empty line like printf "\n"
while true; do # 'while true' or 'while :' is infinite loop
read i
if [ -r $i ] # You probably mean -r (readable) and not -w (writable)
then
cat $i | grep stuff > i2
break # 'break' ends loop
else
echo -n "Oh something is wrong, try again!" # 'echo -n' means print without newline character
sleep 3
fi
done
Измененные места имеют комментарии с описанием.
Как указывали другие, в вашем коде есть логические и синтаксические ошибки. Сайт ShellCheck хорош для отсеивания синтаксических ошибок.
Вот мой взгляд на это. У меня есть две версии кода. Первый (, который я предпочитаю ), не имеет взаимодействия с пользователем, но принимает путь в командной строке. Второй в интерактивном режиме запрашивает путь.
Причина того, что первый не запрашивает путь в интерактивном режиме, заключается в том, что не имеет большого значения, пишет ли пользователь сценария путь в командной строке или в приглашении вашего сценария, а наличие запроса сценария для имени пути дисквалифицирует это от использования, например задание cron или где-либо еще, где не может быть подключен терминал.
#!/bin/sh
pathname=$1
if ! grep 'pattern' <$pathname >i2; then
echo 'Something is wrong' >&2
fi
Описанный выше echo
будет выполнен, когда
$pathname
не может быть прочитан или i2
не может быть записан или $pathname
(это отличается от вашего кода, но см. ниже ). Сообщение об ошибке записывается в стандартную ошибку, как это принято для диагностических сообщений в целом.
С интерактивной подсказкой и задержкой:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
if grep 'pattern' <$pathname >i2; then
break
fi
echo 'Something is wrong' >&2
sleep 3
done
Здесь у нас есть бесконечный цикл, который считывается от пользователя и выходит из цикла, если вызов grep
прошел нормально. Если grep
не удалось по какой-либо причине (одной из трех причин, указанных выше ), имя пути запрашивается снова.
Оба фрагмента кода с отдельным тестом для читаемого файла (grep
допускают сбой, поскольку ничего не находят или не могут записать в свой выходной файл.
Первая не -интерактивная версия:
#!/bin/sh
pathname=$1
if [ ! -r "$pathname" ]; then
echo 'Something is wrong' >&2
fi
grep 'pattern' <$pathname >i2
Затем интерактивная версия:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
if [ -r "$pathname" ]; then
grep 'pattern' <$pathname >i2
break
fi
echo 'Something is wrong' >&2
sleep 3
done
Или,интерактивная версия, в которой цикл имеет дело только с пользовательским вводом и проверкой:
#!/bin/bash
while true; do
read -r -p 'Pathname: ' pathname
[ -r "$pathname" ] && break
echo 'Something is wrong' >&2
sleep 3
done
grep 'pattern' <$pathname >i2