Как считать пробелы в тексте?

Ваш контейнер работает как пользовательский (контейнер без root ), построенный на пользовательских пространствах имен .

Для работы пользовательские контейнеры имеют сопоставление uid / gid для преобразования хоста uid / gid в контейнер uid / gid . Общий диапазон хостов для них составляет 2 ^ 32 в ширину (, начиная с 0, являющегося реальным корневым пользователем ). Исходя из этого, выделенный диапазон для контейнера обычно сохраняется на уровне 2^16 (, что совместимо с историческими диапазонами uid ).

Любой хост uid , у которого нет преобразования диапазона в uid внутри контейнера, будет отображаться как none(соотв.:nogroup для gid) внутри пользовательского контейнера. Поскольку корень этого контейнера не имеет прав на такой uid , он не может изменить его, и операция завершится ошибкой, как при запуске обычным пользователем.

Вот ссылка из Proxmox с описанием вашей проблемы:

https://pve.proxmox.com/wiki/Unprivileged_LXC_containers

However you will soon realise that every file and directory will be mapped to "nobody" (uid 65534), which is fine as long as

  • you do not have restricted permissions set (only group / user readable files, or accessed directories), and
  • you do not want to write files using a specific uid/gid, since all files will be created using the high-mapped (100000+) uids.

Существуют инструменты, предназначенные для преобразования этих диапазонов, поэтому подготовленный макет системного дерева можно сместить в диапазон, подходящий для целевого контейнера. Этот инструмент должен запускаться с хоста (или, по крайней мере, в случае «рекурсивных» контейнеров, контейнер «породил» пространство имен пользователя ). Например:

https://github.com/jirutka/uidmapshift

который является повторной реализацией явно несуществующего uidmapshift проекта nsexec:

https://github.com/fcicq/nsexec

Конечно, вы можете сделать это вручную, рассчитав правильную цель uid:gid и используяchown(с хоста ). Если есть одно значение и простое сопоставление, это должно быть легко.Вот пример (с использованием запущенного пользовательского контейнера LXC):

Контейнер (под названием buster -amd64):

user@buster-amd64:~$ ls -n test
-rw-r--r--. 1 65534 65534 0 Jan 24 21:09 test

root@buster-amd64:/home/user# chown user:user test
chown: changing ownership of 'test': Operation not permitted

Хост (отображает тот же файл):

user@host:~$ ls -n ~/.local/share/lxc/buster-amd64/rootfs/home/user/test
-rw-r--r--. 1 1000 1000 0 Jan 24 22:09 /home/user/.local/share/lxc/buster-amd64/rootfs/home/user/test

Приведенная ниже команда получает процесс инициализации pid (, который равен 1 в контейнере, но здесь значение pid , как показано на хосте ), работающем в контейнере (любой другой процесс контейнера также будет работать):

user@host:~$ lxc-info -Hpn buster-amd64
22926
user@host:~$ cat /proc/22926/uid_map 
         0    1410720      65536

Это сопоставление должно было быть определено в конфигурации LXC:

user@host:~$ grep lxc.idmap ~/.local/share/lxc/buster-amd64/config 
lxc.idmap = u 0 1410720 65536
lxc.idmap = g 0 1410720 65536

Если uid пользовательского контейнера равен 1000 и файл/каталог должен принадлежать этому пользователю, то uid нового хоста должен быть 1410720 + 1000 = 1411720

На хосте, на этот раз как (реальный)root пользователь:

root@host:~# chown 1411720:1411720 ~user/.local/share/lxc/buster-amd64/rootfs/home/user/test 

В случае, если файловая система контейнера (s )не смонтирована напрямую где-то в файловой системе хоста (, например :с использованием резервного хранилища LVM или монтирования tmpfs )и, следовательно, недоступна, это также работает с работающий контейнер (и, вероятно, в любом случае предпочтительнее):

root@host:~# chown 1411720:1411720 /proc/22926/root/home/user/test

А теперь о контейнере:

user@buster-amd64:~$ ls -n test
-rw-r--r--. 1 1000 1000 0 Jan 24 21:09 test

И его пользователь root теперь имеет права на этот файл, потому что он находится в правильном отображении uid / gid .

root@buster-amd64:~# chown root:root ~user/test
root@buster-amd64:~# 

На стороне ядра ведется работа над функцией, называемойshiftfs , которая все еще меняет форму , чтобы облегчить эти проблемы, выполняя это преобразование через связанное монтирование.

2
27.08.2020, 17:36
6 ответов

Вы можете использовать trдля удаления всего, что не является интересующим вас символом, wcдля подсчета оставшихся символов:

ip address show eth0 | grep 'inet ' | tr -d -c ' ' | wc -m

Это хорошо масштабируется для больших объемов текста, trочень эффективно.

Обратите внимание, однако, что в некоторых реализациях tr, включая GNU tr, это правильно работает только для одиночных -байтовых символов (, таких как символ пробела ).

Если вы хотите подсчитывать только начальные пробелы, вам понадобится что-то более мощное, чемtr:

ip address show eth0 | grep 'inet ' | sed 's/[^ ].*$//' | tr -d '\n' | wc -m

Это удаляет каждую часть каждой строки, которая не является начальным пробелом, затем удаляет новые строки и подсчеты.

См. Как подсчитать количество определенных символов в каждой строке? , если вас интересует количество строк.

8
18.03.2021, 23:09

это читается так, как будто вы действительно хотите удалить начальные пробелы

много способов сделать это, предполагая, что вы хотите сделать это в bash. Я нашел это в

https://www.cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html

echo "     This is a test"

# remove leading white space on the output

echo "     This is a test" | sed -e 's/^[ \t]*//'

так что в вашем случае вы могли бы сделать

ip address show eth0 | grep 'inet ' | sed -e 's/^[ \t]*//'

также проверьте Как обрезать начальные и конечные пробелы в каждой строке вывода?

2
18.03.2021, 23:09

Чтобы подсчитать количество пробелов в начале каждой строки, вы можете сделать:

awk -F '[^ ].*' '{print length($1)}'

Который печатает длину (в количестве символов )первого поля, где поля разделены любой последовательностью символов, начинающихся с пробела, отличного от -.

Чтобы сообщить о максимальном количестве пробелов, обнаруженных в начале любой строки ввода (о максимальном отступе ), с GNUwc:

sed 's/[^[:blank:]].*//' | wc -L

Сообщает об этом количестве пробелов с точки зрения ширины экрана на устройстве отображения, где позиции табуляции разделены на 8 столбцов:

$ printf '\tfoo\n' | sed 's/[^[:blank:]].*//' | wc -L
8
$ printf '\u3000foo\n' | sed 's/[^[:blank:]].*//' | wc -L
2

Символ U+3000 (символ идеографического пробела, классифицируемый как пробел в моей локали )представляет собой символ двойной -ширины, закодированный в 3 байта в UTF -8.

Если вы хотите, чтобы максимальная длина сообщалась в виде количества символов:

sed 's/[^[:blank:]].*//;s/./x/g' | wc -L

(s/./x/gпреобразует каждый символ в каждой строке в x, который, как мы знаем, имеет ширину отображения 1 ).

Или по количеству байтов:

sed 's/[^[:blank:]].*//' |
  LC_ALL=C tr -c '\n' '[x*]' | # convert each byte other than newline to x
  wc -L
6
18.03.2021, 23:09
  • Вывести количество начальных пробелов:

    awk '{print match($0,/[^ ]|$/)-1}' file
    

    match($0,/[^ ]|$/)соответствует первому не -пробелу([^ ])или концу -строки -($)и возвращает свою позицию.

  • Распечатать количество пробелов:

    awk -F '[ ]' '{print (NF?NF-1:0)}' file
    

    -F '[ ]'устанавливает в качестве разделителя полей пробел. NF— количество полей. Тернарное выражение означает :«Если NF не равно 0, выведите NF -1, иначе выведите 0». Это потому, что NF равен 0, если строка пуста.

3
18.03.2021, 23:09

Я взял пример ниже

`echo "      praveen"| grep -o "^ *"| awk '{print length($0)}'`6

output

6

Питон

>>> a="      praveen"
>>> import re
>>> k=re.compile(r'^ *')
>>> m=re.search(k,a)
>>> print len(m.group())
6
>>> 
0
18.03.2021, 23:09
$ ip address show eth0 \
| grep -oP '^\h*(?=inet\h)' \
| wc -m;

Это использует GNU grep с режимом PCRE и ищет любые начальные горизонтальные пробелы, также известные как [[ :пробел :]], за которыми следует inet и еще один пробел. Затем мы передаем его wc, чтобы получить количество символов.

Использование gnu awk с переменной FPATH, установленной на набор пробелов.

$... |
 gawk -v FPAT='\\s*' '$0=length($1)""'

Используя сжатие списка python, мы также можем передать grep o/p, чтобы получить количество.

$... | python3 -c 'import sys;print(*[len(l)-len(l.lstrip()) for l in sys.stdin],sep="\n")'

Мы также можем передавать вывод grep в perl.

$..... |
  perl -F'\H' -pE '$_=$F[0]=~y///c'

Здесь мы разбиваем запись на негоризонтальные пробелы, а затем заменяем каждый символ в первом поле, в скалярном контексте возвращаем сделанные переводы. Назначьте его записи и включите опцию -p для автопечати.

0
18.03.2021, 23:09

Теги

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