Как разделить строки с помощью String.Split в C#
Метод String.Split создает массив подстрок, разбивая входную строку по одному или нескольким разделителям. Этот метод зачастую является самым простым способом разделить строку по границам слов. Он также используется для разбиения строк по другим конкретным символам или строкам.
Примеры C# в этой статье выполняются во встроенном средстве выполнения кода и на площадке Try.NET. Нажмите на кнопку Выполнить, чтобы выполнить пример в интерактивном окне. После выполнения кода вы можете изменить его и выполнить измененный код, снова нажав на кнопку Выполнить. Либо в интерактивном окне выполняется измененный код, либо, если компиляция завершается с ошибкой, в интерактивном окне отображаются все сообщения об ошибках компилятора C#.
Следующий код разбивает обычную фразу на массив строк для каждого слова.
string phrase = "The quick brown fox jumps over the lazy dog."; string[] words = phrase.Split(' '); foreach (var word in words) < System.Console.WriteLine($">"); >
Каждый экземпляр знака разделения создает значение в возвращаемом массиве. Последовательные знаки разделения создают пустую строку в виде значения в возвращаемом массиве. В следующем примере показано создание пустой строки с использованием символа пробела в качестве разделителя.
string phrase = "The quick brown fox jumps over the lazy dog."; string[] words = phrase.Split(' '); foreach (var word in words) < System.Console.WriteLine($">"); >
Такое поведение упрощает работу с такими форматами, как файл данных с разделителями-запятыми (CSV), которые представляют табличные данные. Идущие подряд запятые представляют пустой столбец.
Чтобы исключить из возвращаемого массива все пустые строки, можно передать необязательный параметр StringSplitOptions.RemoveEmptyEntries. Для более сложной обработки возвращенной коллекции можно использовать LINQ, чтобы управлять результирующей последовательностью.
String.Split может использовать несколько знаков разделения. В следующем примере используются пробелы, запятые, точки, двоеточия и вкладки в качестве разделительных символов, которые передаются Split в массив. Цикл в конце кода отображает каждое из слов в возвращенном массиве.
char[] delimiterChars = < ' ', ',', '.', ':', '\t' >; string text = "one\ttwo three:four,five six seven"; System.Console.WriteLine($"Original text: ''"); string[] words = text.Split(delimiterChars); System.Console.WriteLine($" words in text:"); foreach (var word in words) < System.Console.WriteLine($">"); >
Последовательные экземпляры любого разделителя создают пустую строку в выходном массиве:
char[] delimiterChars = < ' ', ',', '.', ':', '\t' >; string text = "one\ttwo :,five six seven"; System.Console.WriteLine($"Original text: ''"); string[] words = text.Split(delimiterChars); System.Console.WriteLine($" words in text:"); foreach (var word in words) < System.Console.WriteLine($">"); >
Метод String.Split может принимать массив строк (в этом случае в качестве разделителей при анализе целевой строки используются последовательности символов, а не отдельные символы).
string[] separatingStrings = < "; string text = "one'"); string[] words = text.Split(separatingStrings, System.StringSplitOptions.RemoveEmptyEntries); System.Console.WriteLine($" substrings in text:"); foreach (var word in words)
См. также
- Извлечение элементов из строки
- Руководство по программированию на C#
- Строки
- Регулярные выражения .NET
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Разбиваем строку на подстроки по разделяющим символам своими руками
Приветствую вас, дорогие читатели. В данной статье описана разработка функции разделения строк. Возможно, эта функция может стать для вас хорошей альтернативой, вместо функции strtok из стандартной библиотеки языка Си.
Для разработки использовался компилятор gcc. Код писался под стандарт C99. Он несовместим с С90 из-за наличия объявлений с присваиванием (вида var a = val; а не var a;), а также объявлений в конце функций. Используемые флаги компилятора:
-Wall -Werror -pedantic -std=c99
Вообще говоря, сама задача разбиения строк на подстроки, каждая из которых отделена в исходной строке определённым символом, является довольно распространённой. Очень часто необходимо извлечь из строки слова, разделённые пробелами. Конечно, в стандартной библиотеке языка Си уже есть функция strtok (заголовочный файл ), но она имеет свои побочные эффекты, перечисленные ниже.
- Функция модифицирует исходную строку, разбивая её на лексемы. Она возвращает указатель на саму лексему, или NULL, в случае, когда нет больше лексем. Подробнее о ней можно прочитать здесь.
- Так как функция модифицирует строку, то при передачи ей строчного литерала, будет получено SEGV, поскольку память для таких литеральных строк выделяется в сегменте кода, доступного только для чтения.
- Для последующих вызовов, функции необходимо передавать нулевой указатель (литерал NULL), чтобы она могла продолжить сканирование с последней распознанной лексемы (предыдущего вызова).
- Она не учитывает экранирование символов разделителей.
В виду вышеуказанных причин, мной было принято решение написать свой вариант функции strtok. Новая функция должна выполнять задачу старой, но со следующими ограничениями:
- Не менять оригинальную строку, в которой ищутся лексемы.
- Для каждой найденной лексемы создавать новую строку.
- Сохранять свою текущую позицию, а именно - указатель на подстроку, которая ещё не разбиралась.
- Иметь однородную последовательность вызовов.
- Иметь возможность экранировать символы разделители, при сложных лексемах.
- Иметь возможность работать со строковыми литералами (константами).
Основные шаги при разделении строк
При определении подстрок разделённых между собой каким-либо символом, прежде всего необходимо иметь возможность определять его наличие в строке.
Также необходимо устранить последовательность символов разделителей в начале и в конце строки, для корректной работы функции разбиения.
Наконец, для выделения памяти необходимо будет написать функцию, учитывающая исключительную ситуацию при работе с памятью (ошибки вида SEGV), а также макрос, позволяющий кратко писать вызов такой функции.
Разработка функции
Приступим к разработке. Для начала определим заголовочный файл "str_utils.h", содержащий все прототипы необходимых функций. Реализации функций положим в файл "str_utils.c".
Начнём с функции нахождения символов в строке. Библиотечная функция strchr могла бы решить эту задачу. Но проблема в том, что она не допускает в качестве аргумента строки, в которой надо искать символ, значения NULL. При попытке компилировать с флагами -Wall -Werror , файл с таким аргументом не скомпилируется. Хотя, такую ситуацию можно было бы обработать, вернув NULL. Поэтому был определён свой вариант данной функции с именем contains_symbol. Её прототип выглядит следующим образом:
size_t contains_symbol(char *symbols, char symbol);
Её реализация определена следующим образом (файл "str_utils.c"):
size_t contains_symbol(char *symbols, char symbol) < size_t pos = 1; if(symbols == NULL) return 0; while(*symbols != '\0')< if(*symbols++ == symbol) return pos; pos++; >return 0; >
Данная функция возвращает позицию символа в строке, увеличенную на единицу. Она не учитывает нулевой символ. Если символ не был найден или ей передали NULL,, функция вернёт 0. Её удобно использовать в цикле while, при проверке текущего символа строки на его наличие в другой строке.
Для инкапсуляции работы с памятью был определён отдельный заголовочный файл "mem.h", содержащий следующие прототипы:
void *alloc_mem(size_t nbytes); void *calloc_mem(size_t nelems, size_t elem_size); #define alloc_str(x) ((char *) alloc_mem(x + 1))
Соответствующие функции реализованы в отдельном файле "mem.c":
#include #include void *alloc_mem(size_t nbytes) < char *buf = (char *)malloc(nbytes); if(buf != NULL)< memset(buf, '\0', nbytes); return buf; >exit(-1); > void *calloc_mem(size_t nelems, size_t elem_size) < void *buf = calloc(nelems, elem_size); if(buf != NULL)< return buf; >exit(-1); >
Они выделяют блок памяти в куче, содержащий указанное количество байт, а также дополнительно его обнуляют (функция alloc_mem).
Функция обрезки разделителей строки trim_separators выглядит следующим образом:
/* trims symbols from separators at src string */ /* returns new trimmed string */ char *trim_separators(char *src, char *separators);
char *trim_separators(char *src, char *separators) < if(src == NULL || separators == NULL) return NULL; char *sp = src; while(contains_symbol(separators, *sp)) sp++; /* if it contains only symbols from separators =>NULL */ if(sp - s == strlen(s)) return NULL; char *sp2 = s + strlen(s) - 1; /* last char at src */ while(contains_symbol(separators, *sp2)) sp2--; /* if it contains only symbols from separators => NULL */ if(sp2 < s) return NULL; size_t sz = 0; if(sp2 - sp == 0 && *sp == '\0') return NULL; /* zero byte is not a character */ else if(sp2 - sp == 0)< sz = 1; >else < sz = (sp2 - sp) + 1; >char *res = alloc_mem(sz); memcpy(res, sp, sz);/* copy all chars except last zero byte */ return res; >
В начале мы проверяем на NULL аргументы функции. Если они нулевые, то возвращаем NULL.
Далее, через указатель sp, проходим строку слева направо, пока мы встречаем символы из строки separators. Если мы прошли всю строку, значит она целиком и полностью состоит из сепараторов, следовательно надо удалить все символы, или же просто вернуть NULL.
char *sp = src; while(contains_symbol(separators, *sp)) sp++; /* if it contains only symbols from separators => NULL */ if(sp - s == strlen(s)) return NULL;
Аналогично, далее через указатель sp2, проходим строку справа налево, проверяя, находится ли текущий символ в массиве separators. Если это не так, то мы прерываем цикл, а указатели будут содержать ссылку на первые символы, не являющимися разделителями. Если мы опять прошли всю строку, значит снова придётся удалять всю строку, следовательно, возвращаем NULL.
char *sp2 = s + strlen(s) - 1; /* last char at src */ while(contains_symbol(separators, *sp2)) sp2--; /* if it contains only symbols from separators => NULL */ if(sp2 < s) return NULL;
Наконец, вычисляем длину строки. Если указатели ссылаются на одно и то же место, то в строке был лишь один символ, не являющийся разделителем, а потому размер результата будет равным 1 байту (один лишний байт для нулевого символа учтён в макросе alloc_str). Если же этот единственный символ является нулевым (маркером конца), то возвращаем NULL. Иначе берём разницу между адресами указателями, прибавляем к ней единицу, и получаем длину новой строки. Затем мы просто выделяем память для новой строки и копируем в неё строку, начинающуюся с указателя sp.
Теперь, объединим работу выше написанных функции, в единую функцию get_token().
Код функции get_token дан ниже:
char *get_token(char *src, char *delims, char **next) < if(src == NULL || delims == NULL) return NULL; char *delims_p = delims; /* the end of lexem (points to symbol that follows right after lexem */ char *src_p = trim_separators(src, delims); /* the begining of the lexem */ char *lex_begin = src_p; if(src_p == NULL)< *next = NULL; return NULL; >/* flag that indicates reaching of delimeter */ int flag = 0; while(*src_p != '\0') < flag = 0; while(*delims_p != '\0')< if(*delims_p == *src_p)< flag = 1; break; >delims_p++; > if(flag == 1) break; delims_p = delims; src_p++; > /* now src_p points to the symbol right after lexem */ /* compute lexem size and reset pointers (from trimmed to the original src) */ char *offset; size_t tok_size; offset = (src + strspn(src, delims)); tok_size = (src_p - lex_begin); free(lex_begin); lex_begin = offset; src_p = offset + tok_size; if(*src_p == '\0') *next = NULL; else *next = src_p; /* result token */ char *res = alloc_str(tok_size); memcpy(res, lex_begin, tok_size); return res; >
В ней используется функция обрезки trim_separators(). Функция обрезки возвращает новую строку, и далее сканирование ведётся по ней. В цикле лишь проверяется, не равен ли текущий символ какому-либо символу разделителю из массива символов delims, и если равен, то выйти из цикла. Указатель src_p проходит по сканируемой строке. После цикла он будет указывать на символ, следующий за лексемой (конец лексемы). А начало лексемы сохраняется в указателе lex_begin, который изначально указывает на начало обрезанной, сканируемой строки. После обнаружения границ лексемы, вычисляется её размер (её число символом), а затем сканируемая строка удаляется из динамической кучи. Затем указатели переустанавливаются на позиции в оригинальной строке (первый аргумент функции get_token()), а часть строки, которая ещё не была разобрана, присваивается в качестве содержимого двойному указателю next. Обратите внимание, что next является ссылкой на другой указатель (в данном случае, на указатель строки). Двойной указатель позволяет менять значение переменной типа char *, записывая новый адрес в next. Для первого вызова данной функции, next должен хранить адрес переменной указателя, которая указывает на строку и хранит адрес первой ячейки строки. Однако, при работе с двойным указателем возможна серьёзная и незаметная ошибка, если в качестве начального значения next передать адрес переменной, которая непосредственно указывает на строку, а не адрес переменной копии, которая содержит копию адреса строки. В следующем разделе подробно описана данная ситуация, и показан пример работы данной функции.
Пример работы get_token()
Ниже дан простой рабочий пример функции get_token(). Оригинальная строка с лексемами хранится в указателе test, копия адреса строки (копия переменной test) хранится в переменной copytest. Указатель tok хранит текущую распознанную лексему, а next - сканируемую часть строки. Данная программа разделяет строку test по пробелу и символу табуляции на подстроки, и выводит их. Также она выводит саму строку test до и после работы функции. Как можно убедиться по выводу, оригинальная строка не меняется.
#include #include #include #include "mem.h" #include "str_utils.h" int main(int argc, char **argv) < char *test = " They have a cat.\n \0"; char *copytest = test; char **next = ©test; /* has side effect on copytest */ char *tok = NULL; printf("src:%s\n", test); printf("copytest:%s\n", copytest); while(*next != NULL)< tok = get_token(*next, " \t\0", next); if(tok == NULL) break; printf("%s\n", tok); free(tok); >printf("src after:%s\n", test); printf("copytest after:%s\n", copytest); return 0; >
Вывод данной программы:
src: They have a cat. copytest: They have a cat. They have a cat. src after: They have a cat. copytest:(null)
Обратите внимание, что в цикле есть дополнительная проверка на NULL указателя tok. Дело в том, что при получении последнего слова в строке (а именно "cat.\n"), указатель next будет указывать на подстроку, состоящую лишь из одних пробелов (плюс нулевой символ). Функция trim_separators() для таких строк возвращает NULL, так как по логике придётся урезать все символы в строке. В итоге get_token() также вернёт NULL, поскольку уже ничего не осталось для сканирования. Поэтому переменная tok сохранит значение NULL, на последнем шаге.
Теперь снова по поводу двойного указателя next. Как вы могли заметить, в вышеприведённом коде ему передаётся адрес переменной copytest, а не переменной test. Дело в том, что мы можем нечаянно затереть значение переменной test (именно переменной, а не самой строки). Для примера, изменим код следующим образом. Передадим адрес test в указатель next. В итоге мы получим следующий вывод.
src: They have a cat. copytest: They have a cat. They have a cat. src after:(null) copytest: They have a cat.
Как видите, сама строка не меняется, но изменилось значение переменной test. Теперь она содержит NULL, поскольку на последнем шаге, функция присваивает ей соответствующее значение. Отсюда следует, что операции вида:
*next = addr; *next = NULL;
с двойными указателями (указатель на указатель), тройными, и какой-либо сколь угодно длинной цепочкой указателей создают побочный эффект.
Модификация функции get_token(). Экранирование разделителей
Функция get_token() умеет возвращать новые подстроки (токены) из исходной строки, не меняя её. Однако она совершенно не умеет их экранировать, в случае, когда лексемы представляют собой более сложные объекты. Например, а что если лексема содержит символ, который мы выбрали в качестве разделителя?
Например, вам необходимо выделять значения из формата CSV , где, каждая строка имеет следующий вид:
1233,"John Cenna","Male",4.22,"2004, 2005, 2006",1 1234,"John Doe","Male",4.24,"2001, 2004, 2007",0 1235,"Maria Laws","Female",4.23,"2003, 2006, 2008",1
Данные значения формируют следующую таблицу:
Как разбить строку на слова и записать в масив
Не могу разобраться как разбить строку на слова и сохранить в массив как отдельные слова в языке Си. Пробую через strtok, но к сожалению отделает только первое слово. upd. Получаю от пользователя строку и записываю в массив Пример: input = cd .. argc[0] = cd argc[1] = .. Вот код:
char split(char *commadnForSpilt) < //FIX to strtok int i = 0; char *p = strtok (commadnForSpilt, " "); char *array[3]; while (p != NULL) < array[i++] = p; p = strtok (NULL, " "); >for (i = 0; i
strsplit
C = strsplit( str ) разделения str в пробеле в C . Пробельный символ эквивалентен любой последовательности в наборе .
Если str имеет последовательные пробельные символы, затем strsplit обрабатывает их как один пробел.
C = strsplit( str , delimiter ) разделения str в разделителях, заданных delimiter .
Если str имеет последовательные разделители, без других символов между ними, затем strsplit обрабатывает их как один разделитель. Например, оба strsplit('Hello,world',',') и strsplit('Hello. world',',') возвратите тот же выходной параметр.
C = strsplit( str , delimiter , Name,Value ) задает дополнительные опции разделителя с помощью одного или нескольких аргументов пары "имя-значение". Например, чтобы обработать последовательные разделители как отдельные разделители, можно задать 'CollapseDelimiters',false .
[ C , matches ] = strsplit( ___ ) дополнительно возвращает массив, matches . matches выходной аргумент содержит все случаи разделителей на который strsplit разделения str . Можно использовать этот синтаксис с любым из входных параметров предыдущих синтаксисов.
Примеры
Разделение вектора символа на пробеле
str = 'The rain in Spain.'; C = strsplit(str)
C = 1x4 cell
C массив ячеек, содержащий четыре вектора символов.
Разделение вектора символа значений на определенном разделителе
Разделите вектор символов, который содержит разделенные от запятой значения.
data = '1.21, 1.985, 1.955, 2.015, 1.885'; C = strsplit(data,', ')
C = 1x5 cell
Разделите вектор символов, data , который содержит модули m/s с произвольным числом пробела по обе стороны от текста. Регулярное выражение, \s* , соответствия любой пробельный символ, кажущийся нулем или больше раз.
data = '1.21m/s1.985m/s 1.955 m/s2.015 m/s 1.885m/s'; [C,matches] = strsplit(data,'\s*m/s\s*',. 'DelimiterType','RegularExpression')
C = 1x6 cell
matches = 1x5 cell
В этом случае, вектор последнего знака в C isempty. Этот пустой символьный вектор следует за последним совпадающим разделителем.
Разделение пути на разделителе файлов
myPath = 'C:\work\matlab'; C = strsplit(myPath,'\')
C = 1x3 cell
Разделение вектора символа с несколькими разделителями
Разделите вектор символов на ' ' и 'ain' , обработка нескольких разделителей как один. Задайте несколько разделителей в массиве ячеек из символьных векторов.
str = 'The rain in Spain stays mainly in the plain.'; [C,matches] = strsplit(str,' ','ain'>,'CollapseDelimiters',true)
C = 1x11 cell Columns 1 through 7 Columns 8 through 11
matches = 1x10 cell Columns 1 through 7 Columns 8 through 10
Разделите тот же вектор символов на пробеле и на 'ain' , использование регулярных выражений и обработка нескольких разделителей отдельно.
[C,matches] = strsplit(str,'\s','ain'>,'CollapseDelimiters',. false, 'DelimiterType','RegularExpression')
C = 1x13 cell Columns 1 through 6 Columns 7 through 13
matches = 1x12 cell Columns 1 through 8 Columns 9 through 12
В этом случае, strsplit обрабатывает эти два разделителя отдельно, таким образом, пустые символьные вектора появляются в выходе C между последовательно совпадающими разделителями.
Разделение текста с несколькими, перекрыв разделители
Разделите текст на векторах символов ', ' и ', and ' .
str = 'bacon, lettuce, and tomato'; [C,matches] = strsplit(str,', ',', and '>)
C = 1x3 cell
matches = 1x2 cell
Поскольку списки команд ', ' сначала и ', and ' содержит , strsplit функционируйте разделяет str на первом разделителе и никогда не переходит к второму разделителю.
Если вы инвертируете порядок разделителей, ', and ' берет приоритет.
str = 'bacon, lettuce, and tomato'; [C,matches] = strsplit(str,', and ',', '>)
C = 1x3 cell
matches = 1x2 cell
Входные параметры
str — Введите текст
вектор символов | строковый скаляр
Введите текст в виде вектора символов или строкового скаляра.
Типы данных: char | string
delimiter — Символы-разделители
вектор символов | 1 - n массив ячеек из символьных векторов | 1 - n массив строк
Символы-разделители в виде вектора символов, 1 - n массив ячеек из символьных векторов или 1 - n массив строк. Текст задан в delimiter не появляется в выходе C .
Задайте несколько разделителей в массиве ячеек или массиве строк. strsplit функционируйте разделяет str на элементах delimiter . Порядок, в котором разделители появляются в delimiter не имеет значения, если несколько разделителей не начинают матч в том же символе в str . В этом случае strsplit разделения на первом разделителе соответствия в delimiter .
delimiter может включать следующие escape-последовательности:
Обратная косая черта
Пример: ','
Пример:
Типы данных: char | cell | string
Аргументы name-value
Задайте дополнительные разделенные запятой пары Name,Value аргументы. Name имя аргумента и Value соответствующее значение. Name должен появиться в кавычках. Вы можете задать несколько аргументов в виде пар имен и значений в любом порядке, например: Name1, Value1, . NameN, ValueN .
Пример: 'DelimiterType','RegularExpression' сообщает strsplit обрабатывать delimiter как регулярное выражение.
CollapseDelimiters — Несколько обработка разделителя
1 (true) (значение по умолчанию) | 0 (false)
Несколько обработка разделителя в виде разделенной запятой пары, состоящей из 'CollapseDelimiters' и любой true или false . Если true , затем последовательные разделители в str обработаны как один. Если false , затем последовательные разделители обработаны как отдельные разделители, приводящие к пустому символьному вектору '' элементы между совпадающими разделителями.
Пример: 'CollapseDelimiters',true
DelimiterType 'DelimiterType'
'Simple' (значение по умолчанию) | 'RegularExpression'
Тип разделителя в виде разделенной запятой пары, состоящей из 'DelimiterType' и один из следующих векторов символов.
| 'Simple' | За исключением escape-последовательностей, strsplit обработки delimiter как текст. |
| 'RegularExpression' | strsplit обработки delimiter как регулярное выражение. |
В обоих случаях, delimiter может включать escape-последовательности.
Выходные аргументы
C — Части исходного текста
массив ячеек из символьных векторов | массив строк
Части вектора исходного символа, возвращенного как массив ячеек из символьных векторов или как массив строк. C всегда содержит еще один элемент, чем matches содержит. Поэтому, если str начинается с разделителя, затем первый элемент C не содержит символов. Если str концы с разделителем, затем последняя ячейка в C не содержит символов.
matches — Идентифицированные разделители
массив ячеек из символьных векторов | массив строк
Идентифицированные разделители, возвращенные как массив ячеек из символьных векторов или как массив строк. matches всегда содержит тот меньше элемента, чем выход C содержит. Если str вектор символов или массив ячеек из символьных векторов, затем matches массив ячеек. Если str массив строк, затем matches массив строк.
Советы
- Начиная в R2016b, split функции рекомендуют разделить элементы массива строк.
Расширенные возможности
Основанная на потоке среда
Запустите код в фоновом режиме с помощью MATLAB® backgroundPool или ускорьте код с Parallel Computing Toolbox™ ThreadPool .
Эта функция полностью поддерживает основанные на потоке среды. Для получения дополнительной информации смотрите функции MATLAB Запуска в Основанной на потоке Среде.
Смотрите также
Темы
Введенный в R2013a
Открытый пример
У вас есть модифицированная версия этого примера. Вы хотите открыть этот пример со своими редактированиями?
Документация MATLAB
Поддержка
- MATLAB Answers
- Помощь в установке
- Отчеты об ошибках
- Требования к продукту
- Загрузка программного обеспечения
© 1994-2021 The MathWorks, Inc.
- Условия использования
- Патенты
- Торговые марки
- Список благодарностей
Для просмотра документации необходимо авторизоваться на сайте
Войти
Памятка переводчика
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.