cd ~
Изменения в вашем домашнем каталоге. ~ в начале пути является аббревиатурой, означающей «домашний каталог пользователя».
cd /
Изменяет корневой каталог /. Здесь нет ничего особенного.
cd ~/
Конечная / не имеет никакого значения. Он заставляет ~ интерпретироваться как каталог, но cd делает это в любом случае. (Конечная / имеет значение для символической ссылки на каталог - сравните ls -ld /var/spool/mail и ls -ld /var/spool/mail/.)
cd -
Изменения в каталоге, в котором вы были до предыдущего . Это особый случай команды cd: когда его аргумент -, он делает это.
cd --
С большинством команд, включая cd, аргумент -- означает, что все, что приходит после этого, будет рассматриваться как операнд, а не вариант. Так, например, cd -- -P означает изменение в каталог с именем -P, тогда как cd -P передает параметр -P (что имеет значение, если путь, по которому вы переходите, проходит через символическую ссылку). Если после -- нет аргументов, -- ничего не делает; эта команда эквивалентна простой cd. cd без аргумента, в свою очередь, является ярлыком для cd ~.
cd /.
Эквивалентен cd /, поскольку /. - это тот же каталог, что и / (. в основном полезен сам по себе, означает «текущий каталог»).
cd $HOME
Изменения в вашем домашнем каталоге. Это не удается, если путь к вашему домашнему каталогу содержит пробел или другие символы. Всегда используйте двойные кавычки вокруг переменных подстановок: cd "$HOME".
cd $USR
По всей вероятности, это ничего не значит, потому что в вашей оболочке не определена переменная с именем USR, поэтому выполняемая команда просто [ f37].
Это можно сделать полностью в awk:
$ awk '$1 ~ /kpoint[0-9]/ { file = $1 ".dat" } {print > file}' file
$ head kpoint*
==> kpoint1.dat <==
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
==> kpoint2.dat <==
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Awk также поддерживает > file для перенаправления с некоторыми незначительными отличиями (см. руководство GNU awk для более).
Это можно сделать полностью в awk:
$ awk '$1 ~ /kpoint[0-9]/ { file = $1 ".dat" } {print > file}' file
$ head kpoint*
==> kpoint1.dat <==
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
==> kpoint2.dat <==
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Awk также поддерживает > file для перенаправления с некоторыми незначительными отличиями (см. руководство GNU awk для более).
Это можно сделать полностью в awk:
$ awk '$1 ~ /kpoint[0-9]/ { file = $1 ".dat" } {print > file}' file
$ head kpoint*
==> kpoint1.dat <==
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
==> kpoint2.dat <==
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Awk также поддерживает > file для перенаправления с некоторыми незначительными отличиями (см. руководство GNU awk для более).
В то время как ответ муру является самым простым, существует несколько других способов без использования awk.
Подход с awk в основном заключается в том, что мы пишем конкретное имя файла и измените это имя файла, если и только если мы встретим kpoint в начале строки. Такой же подход можно сделать с помощью Perl:
$ perl -ane '$p=$F[0] if $F[0] =~ /kpoint/;open($f,">>",$p . ".dat"); print $f $_' input.txt
Вот как это работает:
-a флаг позволяет нам использовать специальный @F массив слов, которые были автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk $p=$F[0] if $F[0] =~ /kpoint/ предназначен для изменения $p (который предназначен для префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение соответствия этого шаблона может быть /^ *kpoint/ на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с строкой .dat; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И, наконец, print $f $_ просто печатает любое открытое имя файла. Из вашего примера видно, что каждая запись состоит из 5 строк. Если это константа, мы можем разбить файл таким образом, не полагаясь на сопоставление шаблонов с split. В частности, эта команда:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
В этой опции команды следующие:
-a флаг позволяет нам использовать специальный @F массив слов, которые имеют автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk --numeric-suffixes=1 позволит нам добавлять меняющиеся числа, начиная с 1 до каждого имени файла $p=$F[0] if $F[0] =~ /kpoint/, для изменения $p ( который должен быть префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение этого совпадения шаблонов может быть /^ *kpoint/ input.txt - это файл, который мы пытаемся разделить на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с .dat строка; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И вот как это работает на практике:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
$ cat kpoint01.dat
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
$ cat kpoint02.dat
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Кроме того, мы могли бы добавить --suffix-length=1, чтобы длина каждого числового суффикса была короче, чем kpoint1, а не kpoint01, но это может быть проблемой, если у вас есть большое количество kpoint s.
Это похоже на ответ muru , за исключением того, что мы используем различное совпадение шаблонов, а также другой подход к созданию переменной имени файла через sprintf()
$ awk '/^\ *kpoint/{f=sprintf("%s.dat",$1)};{print > f}' input.txt
Хотя подходы awk и split короче, другие инструменты, такие как Python, хорошо подходят для обработки текста, и мы можем использовать их для реализации большего подробные, но рабочие решения.
Сценарий ниже делает именно это, и он работает над идеей оглянуться назад в список строк, которые мы сохраняем. Сценарий сохраняет строки сохранения до тех пор, пока он не встретит kpoint в начале строки, а это значит, что мы достигли новой записи, что также означает, что нам нужно записать предыдущую запись в соответствующий файл.
#!/usr/bin/env python3
import sys
def write_entry(pref,line_list):
# this function writes the actual file for each entry
with open(".".join([pref,"dat"]),"w") as entry_file:
entry_file.write("".join(line_list))
def main():
prefix = ""
old_prefix = ""
entry=[]
with open(sys.argv[1]) as fd:
for line in fd:
# if we encounter kpoint string, that's a signal
# that we need to write out the list of things
if line.strip().startswith('kpoint'):
prefix=line.strip().split()[0]
# This if statement counters special case
# when we just started reading the file
if not old_prefix:
old_prefix = prefix
entry.append(line)
continue
write_entry(old_prefix,entry)
old_prefix = prefix
entry=[]
# Keep storing lines. This works nicely after old
# entry has been cleared out.
entry.append(line)
# since we're looking backwards, we need one last call
# to write last entry when input file has been closed
write_entry(old_prefix,entry)
if __name__ == '__main__': main()
Почти та же идея, что и подход Perl - мы продолжаем записывать все в определенное имя файла и изменять имя файла только тогда, когда находим строку с kpoint.
#!/usr/bin/env bash
while IFS= read -r line;
do
case "$line" in
# We found next entry. Use word-splitting to get
# filename into fname variable, and truncate that filename
*kpoint[0-9]*) read fname trash <<< $line &&
echo "$line" > "$fname".dat ;;
# That's just a line within entry. Append to
# current working file
*) echo "$line" >> "$fname".dat ;;
esac
done < "$1"
# Just in case there are trailing lines that weren't processed
# in while loop, append them to last filename
[ -n "$line" ] && echo "$line" >> "$fname".dat ;
Хотя ответ муру является самым простым, существует несколько других способов без использования awk.
Подход с awk в основном заключается в том, что мы пишем конкретное имя файла и измените это имя файла, если и только если мы встретим kpoint в начале строки. Такой же подход можно сделать с помощью Perl:
$ perl -ane '$p=$F[0] if $F[0] =~ /kpoint/;open($f,">>",$p . ".dat"); print $f $_' input.txt
Вот как это работает:
-a флаг позволяет нам использовать специальный @F массив слов, которые были автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk $p=$F[0] if $F[0] =~ /kpoint/ предназначен для изменения $p (который предназначен для префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение соответствия этого шаблона может быть /^ *kpoint/ на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с строкой .dat; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И, наконец, print $f $_ просто печатает любое открытое имя файла. Из вашего примера видно, что каждая запись состоит из 5 строк. Если это константа, мы можем разбить файл таким образом, не полагаясь на сопоставление шаблонов с split. В частности, эта команда:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
В этой опции команды следующие:
-a флаг позволяет нам использовать специальный @F массив слов, которые имеют автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk --numeric-suffixes=1 позволит нам добавлять меняющиеся числа, начиная с 1 до каждого имени файла $p=$F[0] if $F[0] =~ /kpoint/, для изменения $p ( который должен быть префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение этого совпадения шаблонов может быть /^ *kpoint/ input.txt - это файл, который мы пытаемся разделить на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с .dat строка; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И вот как это работает на практике:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
$ cat kpoint01.dat
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
$ cat kpoint02.dat
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Кроме того, мы могли бы добавить --suffix-length=1, чтобы длина каждого числового суффикса была короче, чем kpoint1, а не kpoint01, но это может быть проблемой, если у вас есть большое количество kpoint s.
Это похоже на ответ muru , за исключением того, что мы используем различное совпадение шаблонов, а также другой подход к созданию переменной имени файла через sprintf()
$ awk '/^\ *kpoint/{f=sprintf("%s.dat",$1)};{print > f}' input.txt
Хотя подходы awk и split короче, другие инструменты, такие как Python, хорошо подходят для обработки текста, и мы можем использовать их для реализации большего подробные, но рабочие решения.
Сценарий ниже делает именно это, и он работает над идеей оглянуться назад в список строк, которые мы сохраняем. Сценарий сохраняет строки сохранения до тех пор, пока он не встретит kpoint в начале строки, а это значит, что мы достигли новой записи, что также означает, что нам нужно записать предыдущую запись в соответствующий файл.
#!/usr/bin/env python3
import sys
def write_entry(pref,line_list):
# this function writes the actual file for each entry
with open(".".join([pref,"dat"]),"w") as entry_file:
entry_file.write("".join(line_list))
def main():
prefix = ""
old_prefix = ""
entry=[]
with open(sys.argv[1]) as fd:
for line in fd:
# if we encounter kpoint string, that's a signal
# that we need to write out the list of things
if line.strip().startswith('kpoint'):
prefix=line.strip().split()[0]
# This if statement counters special case
# when we just started reading the file
if not old_prefix:
old_prefix = prefix
entry.append(line)
continue
write_entry(old_prefix,entry)
old_prefix = prefix
entry=[]
# Keep storing lines. This works nicely after old
# entry has been cleared out.
entry.append(line)
# since we're looking backwards, we need one last call
# to write last entry when input file has been closed
write_entry(old_prefix,entry)
if __name__ == '__main__': main()
Почти та же идея, что и подход Perl - мы продолжаем записывать все в определенное имя файла и изменять имя файла только тогда, когда находим строку с kpoint.
#!/usr/bin/env bash
while IFS= read -r line;
do
case "$line" in
# We found next entry. Use word-splitting to get
# filename into fname variable, and truncate that filename
*kpoint[0-9]*) read fname trash <<< $line &&
echo "$line" > "$fname".dat ;;
# That's just a line within entry. Append to
# current working file
*) echo "$line" >> "$fname".dat ;;
esac
done < "$1"
# Just in case there are trailing lines that weren't processed
# in while loop, append them to last filename
[ -n "$line" ] && echo "$line" >> "$fname".dat ;
Хотя ответ муру является самым простым, существует несколько других способов без использования awk.
Подход с awk в основном заключается в том, что мы пишем конкретное имя файла и измените это имя файла, если и только если мы встретим kpoint в начале строки. Такой же подход можно сделать с помощью Perl:
$ perl -ane '$p=$F[0] if $F[0] =~ /kpoint/;open($f,">>",$p . ".dat"); print $f $_' input.txt
Вот как это работает:
-a флаг позволяет нам использовать специальный @F массив слов, которые были автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk $p=$F[0] if $F[0] =~ /kpoint/ предназначен для изменения $p (который предназначен для префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение соответствия этого шаблона может быть /^ *kpoint/ на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с строкой .dat; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И, наконец, print $f $_ просто печатает любое открытое имя файла. Из вашего примера видно, что каждая запись состоит из 5 строк. Если это константа, мы можем разбить файл таким образом, не полагаясь на сопоставление шаблонов с split. В частности, эта команда:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
В этой опции команды следующие:
-a флаг позволяет нам использовать специальный @F массив слов, которые имеют автоматически отделяется от каждой строки входного файла. Таким образом, $F[0] относится к первому слову, так же как $1 в awk --numeric-suffixes=1 позволит нам добавлять меняющиеся числа, начиная с 1 до каждого имени файла $p=$F[0] if $F[0] =~ /kpoint/, для изменения $p ( который должен быть префиксной переменной) тогда и только тогда, когда kpoint находится в строке. Улучшение этого совпадения шаблонов может быть /^ *kpoint/ input.txt - это файл, который мы пытаемся разделить на каждой итерации, которую мы открываем для добавления файла с именем $p, соединенным с .dat строка; обратите внимание, что добавление части важно. Если вы хотите иметь четкий пробег, вы, вероятно, захотите избавиться от старых файлов kpoint. Если мы хотим, чтобы файл всегда был создан свежим и перезаписанным, мы можем перезаписать исходную команду как:$ perl -ane 'if ($F[0] =~ /kpoint/){$p=$F[0]; open($f,">",$p . ".dat")}; print $f $_' input.txt
И вот как это работает на практике:
$ split --additional-suffix=".dat" --numeric-suffixes=1 -l 5 input.txt kpoint
$ cat kpoint01.dat
kpoint1 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
$ cat kpoint02.dat
kpoint2 : 0.0000 0.0000 0.0000
band No. band energies occupation
1 -52.8287 2.00000
2 -52.7981 2.00000
3 -52.7981 2.00000
Кроме того, мы могли бы добавить --suffix-length=1, чтобы длина каждого числового суффикса была короче, чем kpoint1, а не kpoint01, но это может быть проблемой, если у вас есть большое количество kpoint s.
Это похоже на ответ muru , за исключением того, что мы используем различное совпадение шаблонов, а также другой подход к созданию переменной имени файла через sprintf()
$ awk '/^\ *kpoint/{f=sprintf("%s.dat",$1)};{print > f}' input.txt
Хотя подходы awk и split короче, другие инструменты, такие как Python, хорошо подходят для обработки текста, и мы можем использовать их для реализации большего подробные, но рабочие решения.
Сценарий ниже делает именно это, и он работает над идеей оглянуться назад в список строк, которые мы сохраняем. Сценарий сохраняет строки сохранения до тех пор, пока он не встретит kpoint в начале строки, а это значит, что мы достигли новой записи, что также означает, что нам нужно записать предыдущую запись в соответствующий файл.
#!/usr/bin/env python3
import sys
def write_entry(pref,line_list):
# this function writes the actual file for each entry
with open(".".join([pref,"dat"]),"w") as entry_file:
entry_file.write("".join(line_list))
def main():
prefix = ""
old_prefix = ""
entry=[]
with open(sys.argv[1]) as fd:
for line in fd:
# if we encounter kpoint string, that's a signal
# that we need to write out the list of things
if line.strip().startswith('kpoint'):
prefix=line.strip().split()[0]
# This if statement counters special case
# when we just started reading the file
if not old_prefix:
old_prefix = prefix
entry.append(line)
continue
write_entry(old_prefix,entry)
old_prefix = prefix
entry=[]
# Keep storing lines. This works nicely after old
# entry has been cleared out.
entry.append(line)
# since we're looking backwards, we need one last call
# to write last entry when input file has been closed
write_entry(old_prefix,entry)
if __name__ == '__main__': main()
Почти та же идея, что и подход Perl - мы продолжаем записывать все в определенное имя файла и изменять имя файла только тогда, когда находим строку с kpoint.
#!/usr/bin/env bash
while IFS= read -r line;
do
case "$line" in
# We found next entry. Use word-splitting to get
# filename into fname variable, and truncate that filename
*kpoint[0-9]*) read fname trash <<< $line &&
echo "$line" > "$fname".dat ;;
# That's just a line within entry. Append to
# current working file
*) echo "$line" >> "$fname".dat ;;
esac
done < "$1"
# Just in case there are trailing lines that weren't processed
# in while loop, append them to last filename
[ -n "$line" ] && echo "$line" >> "$fname".dat ;