Alle anderen Antworten, die hier und in verlinkten Fragen gegeben werden, scheitern auf unterschiedliche Weise bei verschiedenen möglichen FS-Werten. Einige lassen führende und/oder nachgestellte Leerzeichen, einige konvertieren jeden FS in den OFS, einige verlassen sich auf eine Semantik, die nur gilt, wenn FS der Standardwert ist, einige verlassen sich auf die Negierung von FS in einem Klammerausdruck, der bei einem mehrstelligen FS fehlschlägt, usw.
Um dies robust für jede FS zu tun, verwenden Sie GNU awk für das 4. arg an split():
$ cat tst.awk
{
split($0,flds,FS,seps)
for ( i=n; i<=NF; i++ ) {
printf "%s%s", flds[i], seps[i]
}
print ""
}
$ printf 'a b c d\n' | awk -v n=3 -f tst.awk
c d
$ printf ' a b c d\n' | awk -v n=3 -f tst.awk
c d
$ printf ' a b c d\n' | awk -v n=3 -F'[ ]' -f tst.awk
b c d
$ printf ' a b c d\n' | awk -v n=3 -F'[ ]+' -f tst.awk
b c d
$ printf 'a###b###c###d\n' | awk -v n=3 -F'###' -f tst.awk
c###d
$ printf '###a###b###c###d\n' | awk -v n=3 -F'###' -f tst.awk
b###c###d
Beachten Sie, dass ich split() oben verwende, weil das 3rg-Arg ein Feldtrenner und nicht nur ein Regexp wie das 2. Argument von match(). Der Unterschied besteht darin, dass Feldtrennzeichen im Vergleich zu Regexps eine zusätzliche Semantik haben, wie z. B. das Überspringen führender und/oder nachfolgender Leerzeichen, wenn das Trennzeichen ein einzelnes Leerzeichen ist - wenn Sie eine while(match())-Schleife oder irgendeine Form von *sub() verwenden wollten, um das oben genannte zu emulieren, müssten Sie Code schreiben, um diese Semantik zu implementieren, während split() sie bereits für Sie implementiert.