Як я можу розділити літери слова з кожною буквою в окремому рядку?
Наприклад, враховуючи, що "StackOver"
я хотів би бачити
S
t
a
c
k
O
v
e
r
Я новачок у баші, тому у мене немає поняття, з чого почати.
Як я можу розділити літери слова з кожною буквою в окремому рядку?
Наприклад, враховуючи, що "StackOver"
я хотів би бачити
S
t
a
c
k
O
v
e
r
Я новачок у баші, тому у мене немає поняття, з чого почати.
Відповіді:
Я б використав grep
:
$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r
або sed
:
$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r
І якщо порожній пробіл в кінці є проблемою:
sed 's/\B/&\n/g' <<<"StackOver"
Все це припускаючи GNU / Linux.
Here string
, еквівалент бруто-моду echo foo | ...
лише меншого набору тексту. Дивіться tldp.org/LDP/abs/html/x17837.html
.
на \B
(не відповідає межі слова).
sed
типу:sed -et -e's/./\n&/g;//D'
Ви можете перерватися на клафери графеми замість символів, якщо наміром буде друкувати текст вертикально. Наприклад, з e
гострим акцентом:
З кластерними графемами ( e
з його гострим акцентом було б одне згруповання графеми):
$ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
S
t
é
p
h
a
n
e
(або grep -Po '\X'
з GNU grep, побудований за допомогою підтримки PCRE)
З символами (тут з GNU grep
):
$ printf '%s\n' $'Ste\u301phane' | grep -o .
S
t
e
p
h
a
n
e
fold
призначений для розбиття на символи, але GNU fold
не підтримує багатобайтові символи, тому він переривається на байти:
$ printf '%s\n' $'Ste\u301phane' | fold -w 1
S
t
e
�
�
p
h
a
n
e
У StackOver, який складається лише з символів ASCII (так, один байт на символ, один символ на кластер графем), усі три давали б однаковий результат.
grep -Po
це не робить того, що можна було б очікувати (як grep -P
це роблять).
grep -Po .
знаходить символів (а поєднання гострого акценту за символом нового рядка є недійсним) та grep -Po '\X'
знаходить кластери графеми для мене. Вам може знадобитися остання версія grep та / або PCRE, щоб вона працювала належним чином (або спробуйте grep -Po '(*UTF8)\X'
)
Нижче буде загальним:
$ awk -F '' \
'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
echo StackOver | sed -e 's/./&\n/g'
S
t
a
c
k
O
v
e
r
Оскільки ви спеціально попросили відповіді в bash, ось спосіб зробити це в чистому стилі:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
Зауважте, що цей параметр набере новий рядок наприкінці " тут документа ". Якщо ви хочете цього уникнути, але все ж повторіть символи за допомогою циклу bash, використовуйте printf
для уникнення нового рядка.
printf StackOver | while read -rn1; do echo "$REPLY" ; done
Ви можете використовувати fold (1)
команду. Це ефективніше ніж grep
і sed
.
$ time grep -o . <bigfile >/dev/null
real 0m3.868s
user 0m3.784s
sys 0m0.056s
$ time fold -b1 <bigfile >/dev/null
real 0m0.555s
user 0m0.528s
sys 0m0.016s
$
Важливою відмінністю є те, що складка відтворює порожні рядки у висновку:
$ grep -o . <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$ fold -b1 <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$
Ви можете обробляти багатобайтові символи, наприклад:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
Що може бути дуже зручно, коли ви працюєте з введенням в реальному часі, оскільки там немає буферизації, і символ друкується, як тільки він стає цілим .
sed
сценарії. Я зараз, швидше за все, не пишу про них - я досить сонний. це дійсно корисно, хоча, читаючи термінал.
dd
це розбиває багатобайтові символи, тому вихід не буде більше тексту, тому поведінка sed буде не визначена відповідно до POSIX.
Ви також можете використовувати межі слів ..
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
В bash:
Це працює з будь-яким текстом і лише з внутрішніми файлами bash (жодна зовнішня утиліта не називається), тож має бути швидкою на дуже коротких рядках.
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")
Вихід:
S
t
é
p
h
a
n
e
á
à
é
è
ë
ê
ế
e
Якщо нормально змінити IFS та змінити позиційні параметри, ви також можете уникнути виклику підрозділу:
str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
set -- "${BASH_REMATCH[@]:1}"
IFS=$'\n'
echo "$*"
s=stackoverflow;
$ time echo $s | fold -w1
s
t
a
c
k
o
v
e
r
real 0m0.014s
user 0m0.000s
sys 0m0.004s
оновлення тут - хекітний | найшвидший | pureBashBase спосіб!
$ time eval eval printf \'%s\\\\n\' \\\${s:\{0..$((${#s}-1))}:1}
s
t
a
c
k
o
v
e
r
real 0m0.001s
user 0m0.000s
sys 0m0.000s
для більшої дивовижності
function foldh ()
{
if (($#)); then
local s="$@";
eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
else
while read s; do
eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
done;
fi
}
function foldv ()
{
if (($#)); then
local s="$@";
eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
else
while read s; do
eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
done;
fi
}
fold -b1
?
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
це розділить ваше слово і збереже його у масиві var
.
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done