эхо-перенаправление добавляет пробелы

KDE Connect сделает это, если вы используете KDE (, но, вероятно, не используете Fedora ). Существует также реализация GNOME, GSConnect , но я не могу за это поручиться (Я запускаю KDE ). Они подключаются к вашему телефону через зашифрованное соединение в локальной сети. Облачный сервис не задействован.

Хотя, честно говоря, проще всегоhttps://messages.android.com/— хотя это будет направлять ваши SMS-сообщения через Google со всеми последствиями для конфиденциальности, которые имеет (, что может быть не хуже, поскольку вы уже используете Android )..

-1
28.11.2021, 05:18
2 ответа

Утилита echoвставляет пробелы, но только как разделители между аргументами при их выводе:

$ echo 1    2 3       4 'A B     C'
1 2 3 4 A B     C

Пробелы между Bи Cсохраняются, поскольку они являются частью одного и того же аргумента для echo.

Таким образом, дело не в том, что echo— это вставка пробелов, а в том, что ваши данные уже содержат пробелы.

Я предполагаю, что одинарные кавычки, которые вы видите, являются частью вывода lsв вашей системе (см. Почему 'ls' внезапно заключает элементы с пробелами в одинарные кавычки?)или, возможно, часть вывода трассировки оболочки во время ее работы с set -xактивным (см. Почему bash добавляет одинарные кавычки к незакавыченным неудачным расширениям пути в команде перед ее выполнением?). То есть на самом деле это не часть имен файлов, а всего лишь способ отображения имен каким-то инструментом.

Предположим, например, что ваш ввод выглядит как

174.18.418.83, 10.404.401.94, 53144
174.18.418.83, 10.404.401.94, 53144
174.18.418.83, 10.404.401.94, 53144

Вы заметите, что после запятых есть пробелы. Если вы читаете второе поле из вышеуказанного файла, используя запятую в качестве разделителя, вы сохраните пробел (с )в начале поля, и если вы используете эти данные в качестве имени файла,имя файла будет начинаться с пробела.

(Внимательный читатель заметит, что код в вопросе использует переменную lineбез кавычек, это означает, что оболочка разделит значение переменной на пробелы и представит echoс отдельными аргументами, такими как 174.18.418.83,, 10.404.401.94,и 53144. Таким образом, верно в том смысле, что именно echoвставляет пробелы, которые необходимо удалить, но этого бы не произошло, если бы в данных не было пробелов/табуляции для начала. См. также Когда необходимо двойное -цитирование?)

Решение состоит в том, чтобы использовать как запятую, так и любой последующий пробел в качестве разделителя сawk:

awk -F ',[[:blank:]]*' '{ print $2 }'

Выражение ,[[:blank:]]*соответствует запятой, за которой следует любое количество пробелов. «Пробел» — это пробел или табуляция. Вы можете изменить это на, *("запятая, пробел, звездочка" ), если вы знаете, что у вас есть буквальные пробелы.

Теперь, чтобы избежать вызоваawkтри раза для каждой строки во входном файле.

Оператор printв awkможно «перенаправить» почти так же, как вы можете перенаправить вывод в оболочке, используя >, за которым следует имя файла.

Имя файла, которое вы хотите использовать, это то, что указано во втором поле с добавлением .tmp.

Это означает, что вы можете заменить весь цикл в своем вопросе следующей одиночной командой awk:

awk -F ',[[:blank:]]*' '{ print $1 > ($2 ".tmp") }' limpio.tmp

Выражение ($2 ".tmp")возвращает строку, полученную в результате добавления .tmpк тому, что находится во втором поле.

Использование >с printозначает, что выходной файл будет создан или усечен (очищен )в первый printи что только последующие printс тем же именем будут добавлять новые строки. Если бы вы использовали >>вместо >, первое printдополняло бы файл, а не обрезало его.

Здесь нет постройки -для проверки на вменяемость,поэтому приведенное выше может стереть важные файлы в любом месте системы, где у вас есть доступ для записи, в зависимости от того, что находится во 2-м столбце ввода.

Если вы используете GNU awk, это все, что вам нужно сделать. Но если вы используете какой-то другой awkи вам нужно записать в огромное количество файлов, вам может потребоваться вручную вызвать close()для файлов по мере их обработки, или у вас могут закончиться доступные файловые дескрипторы.

awk -F ',[[:blank:]]*' '{ fn = $2 ".tmp"; print $1 >>fn; close(fn) }' limpio.tmp

Здесь я сохраняю имя выходного файла в переменной fn. Затем я добавляю вывод в этот файл, а затем закрываю файл. Это гарантирует, что я не исчерпаю доступные файловые дескрипторы, но также требует, чтобы я всегда использовал >>с printи вручную очищал (удалял )выходные файлы, если мне нужно запустить awkеще раз.

GNU awkотслеживает, сколько файловых дескрипторов было открыто, и при необходимости начинает их закрывать (и повторно -открывает файлы для добавления, если позже в файл потребуется записать дополнительные данные ).

См. также:

3
28.11.2021, 09:12

Это исходный код, который вы разместили:

cat limpio.tmp | while read line; do
  srcip=$(echo $line | awk -F"," '{print $1}')
  destip=$(echo $line | awk -F"," '{print $2}')
  port=$(echo $line | awk -F"," '{print $NF}')
  echo "${srcip}" >> "$destip.tmp"
done

Это излишне сложно. Видя, что вы читаете поля, разделенные запятыми, вы можете читать их прямо в переменные:

while IFS=$' \t\n,' read -r srcip destip port junk ;do
  echo "$srcip" >> "${destip}.tmp"
done <limpio.tmp
0
28.11.2021, 06:24

Теги

Похожие вопросы