Скажем, у меня есть строка как
name = xyz
здесь после имени есть табуляция, а после '=' произвольное количество пробелов.
Мне нужен вывод как
name=xyz
Итак, как я могу удалить как вкладки, так и случайное количество пробелов из вышеупомянутой строки, используя функцию sed или awk и tcl regsub. Помощь высоко ценится. Спасибо.
Я пытался
[regsub -all { +} $str ""]
Это удаляет случайное количество пробелов из $str
, но вкладки все еще присутствуют.
\s
соответствует как символу табуляции, так и пробелу. Тогда не могли бы вы попробовать:
[regsub -all {\s+} $str ""]
Потенциальная проблема здесь в том, что он удалит пустые символы в любом месте, независимо от отношения к знаку =
.
Безопаснее будет сказать:
[regsub {\t=\s*} $str " = "]
который удаляет символ табуляции перед =
и пробелы после =
.
Немного проще: regsub {\s*=\s*} $str " = "
-- не нужно ничего захватывать.
Кроме того, если есть странная строка, такая как set str "name\t= foo\t\t= bar"
, ваше регулярное выражение заменит последнее = (из-за жадного начального .+
), а мое заменит первое.
@glennjackman спасибо за предложение. Я обновил ответ соответственно.
Спасибо за вклад, сработало как шарм, а также было легко понять.
Спасибо за ваш отзыв! Приятно знать, что это работает. Если вы считаете, что мой ответ хорошо решает вашу проблему, я был бы признателен, если бы вы могли принять мой ответ, нажав на галочку рядом с ответом. БР.
Вот также решение с использованием sed
myvar=$(sed -E 's/\s*=\s*/=/g' <<<$myvar)
или, чтобы быть более портативным, вы можете использовать [[:space:]]
вместо \s
myvar=$(sed -E 's/[[:space:]]*=[[:space:]]*/=/g' <<<$myvar)
Здесь каждое вхождение =
, окруженное любым количеством пробельных символов, будет заменено только =
без каких-либо пробелов.
Я бы использовал GNU AWK
для этой задачи следующим образом
echo "name = xyz" | awk 'BEGIN{OFS = ""}{$1=$1;print}'
дает результат
name=xyz
Объяснение: GNU AWK
предполагает, что разделителем полей является один или несколько пробельных символов, которые соответствуют вашему варианту использования, я установил OFS
на пустую строку, поэтому между полями ничего не будет, $1=$1
запускает перестройку строки, print
печатает ее. Если вы хотите узнать больше о OFS
, прочитайте 8 мощных встроенных переменных Awk — FS, OFS, RS, ORS, NR, NF, FILENAME, FNR
(проверено в GNU Awk 5.0.1)
Использование замены параметра bash
:
$ str='name = xyz'
$ str = "${str//[ \t]/}"
$ echo "$str"
name=xyz
# or
$ str='name = xyz'
$ str = "${str//[[:space:]]/}"
$ echo "$str"
name=xyz
Другое решение с awk
:
echo 'name = xyz' | awk NF++ OFS=
Результаты в
name=xyz
Пожалуйста, не публикуйте только код в качестве ответа, но также объясните, что делает ваш код и как он решает проблему вопроса. Ответы с объяснением, как правило, более полезны и качественны, и с большей вероятностью привлекут положительные голоса.
@MarkRotteveel: просто в посте под моим уже есть ссылка на объяснение того, для чего нужны NF
и OFS
. Вы хотите, чтобы я продублировал это? или мне тоже нужно объяснять ++
? На самом деле, мое решение - это наименее подробный способ выразить то, что Давео сказал ниже, с очень тонкой разницей - мое решение пропускает пустые строки, ее/его/ее версия распечатывает их. @Общее недовольство: я просто предпочитаю стиль четко разграничивать входные данные теста и результирующие выходные разделы из самого кода.
Да, вы должны сделать свой ответ как можно более полным с достаточным количеством информации, чтобы понять ваше решение.
@MarkRotteveel: определить достаточно. Могу ли я предположить, что у них есть минимальное понимание того, что означает stdin
, или мне нужно также включить учебник по unix?
Пожалуйста, прочтите это перед повторным откатом.
@GeneralGrievance: и все же мой первоначальный макет визуально разграничил ввод, код и вывод, так что избыточное многословие, такое как «Результаты в», не нужно. Вы можете относиться к другим людям по-своему, но не клевещите и не клевещите на меня, применяя эти снисходительные и покровительственные заголовки разделов, как если бы они исходили из моих уст. Наверное, нужно снова включить Оби-Вана в мой быстрый набор.
Вы неправильно визуально обрисовали код. Когда вы используете блок-цитаты, вы говорите, что это сказал другой источник, см. рекомендации по ссылкам. Поскольку это не было намерением, редактирование для удаления было оправдано. На столе есть много действительных вариантов того, что вы намеревались сделать, я только что предложил один. Вы также можете редактировать. Только не злоупотребляйте форматированием.
Удивительно, но этому вопросу уделялось много внимания. Итак, вношу свой взгляд на задачу. В Tcl вместо использования regsub вы можете использовать внутренний синтаксический анализатор списка, чтобы отбрасывать разделительные символы:
join [list {*}$str] ""
Это, безусловно, зависит от того, полностью ли вы контролируете входную строку. Он должен соответствовать допустимому строковому представлению списка Tcl.
Несмотря на то, что команда
tr
не была одной из упомянутых вами опций, это может быть самый простой способ решить проблему, если она у вас есть. Передача ввода черезtr -d '[:blank:]'
удалит все пробелы (включая повторяющиеся символы), сохраняя при этом новые строки и переводы строк.