GNU/Linux >> Znalost Linux >  >> Linux

Jak posunout řádek v textovém souboru nahoru nebo dolů o jeden řádek?

Mám nějaké textové soubory a chtěl bych mít možnost přesunout libovolný řádek v libovolném souboru nahoru nebo dolů o jeden řádek (řádky na začátku nebo na konci souboru by zůstaly tam, kde jsou). Mám nějaký fungující kód, ale zdá se mi to zmatečné a nejsem přesvědčen, že mám pokryty všechny případy hran, takže by mě zajímalo, jestli existuje nějaký nástroj nebo paradigma, které to dělá lépe (např. snáze pochopit kód (pro jiné čtenáře nebo mě za 6 měsíců), snadněji se ladí a snáze se udržuje; „efektivnější“ není příliš důležité).

move_up() {
  # fetch line with head -<line number> | tail -1
  # insert that one line higher
  # delete the old line
  sed -i -e "$((line_number-1))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
}

move_down() {
  file_length=$(wc -l < "$file")
  if [[ "$line_number" -ge $((file_length - 1)) ]]; then
    # sed can't insert past the end of the file, so append the line
    # then delete the old line
    echo $(head -$line_number "$file" | tail -1) >> "$file"
    sed -i "${line_number}d" "$file"
  else
    # get the line, and insert it after the next line, and delete the original
    sed -i -e "$((line_number+2))i$(head -$line_number $file | tail -1)" -e "${line_number}d" "$file"
  fi
}

Mohu provádět kontrolu chyb vstupů uvnitř nebo vně těchto funkcí, ale bonusové body, pokud jsou špatné vstupy (jako necelá čísla, neexistující soubory nebo čísla řádků větší než délka souboru) zpracovány rozumně.

Chci, aby to běželo ve skriptu Bash na moderních systémech Debian/Ubuntu. Nemám vždy přístup root, ale mohu očekávat, že budou nainstalovány „standardní“ nástroje (předpokládejme sdílený webový server) a může mít možnost požádat o instalaci dalších nástrojů, pokud mohu požadavek odůvodnit (ačkoli méně externích závislostí je vždy lepší).

Příklad:

$ cat b
1
2
3
4
$ file=b line_number=3 move_up
$ cat b
1
3
2
4
$ file=b line_number=3 move_down
$ cat b
1
3
4
2
$ 

Přijatá odpověď:

Podobné jako Archemar Tento návrh byste mohli naskriptovat pomocí ed :

printf %s\n ${linenr}m${addr} w q | ed -s infile

tj.

linenr                      #  is the line number
m                           #  command that moves the line
addr=$(( linenr + 1 ))      #  if you move the line down
addr=$(( linenr - 2 ))      #  if you move the line up
w                           #  write changes to file
q                           #  quit editor

např. přesunout linku č. 21 o jeden řádek výše:

printf %s\n 21m19 w q | ed -s infile

přesunout linku č. 21 o řádek níže:

printf %s\n 21m22 w q | ed -s infile

Ale protože potřebujete pouze posunout určitý řádek nahoru nebo dolů o jeden řádek, můžete také říci, že prakticky chcete prohodit dva po sobě jdoucí řádky. Seznamte se s sed :

sed -i -n 'addr{h;n;G};p' infile

tj.

addr=${linenr}           # if you move the line down
addr=$(( linenr - 1 ))   # if you move the line up
h                        # replace content of the hold  buffer with a copy of the pattern space
n                        # read a new line replacing the current line in the pattern space  
G                        # append the content of the hold buffer to the pattern space
p                        # print the entire pattern space

např. přesunout linku č. 21 o jeden řádek výše:

sed -i -n '20{h;n;G};p' infile

přesunout linku č. 21 o řádek níže:

sed -i -n '21{h;n;G};p' infile

Použil jsem gnu sed syntaxe výše. Pokud jde o přenositelnost:

sed -n 'addr{
h
n
G
}
p' infile

Kromě toho obvyklé kontroly:soubor existuje a lze do něj zapisovat; file_length > 2; line_no. > 1; line_no. < file_length;


Linux
  1. Jak přidat čísla řádků do textových souborů v systému Linux

  2. Jak vložit text před první řádek souboru?

  3. Jak analyzovat každý řádek textového souboru jako argument příkazu?

  1. Jak přejít o jeden adresář dolů?

  2. Jak přidat záhlaví a řádek upoutávky do souboru v Linuxu

  3. VIM:jak přejít na přesnou linku na Ubuntu

  1. Jak najít nesrovnatelné závorky v textovém souboru?

  2. Jak se dotknout souboru a mkdir v případě potřeby na jednom řádku

  3. Jak nahrát jeden soubor pomocí FTP z příkazového řádku?