我想在Bash shell脚本中按字母顺序排列两种模式。
给出以下输入文件:
aaa
bbb
PATTERN1
foo
bar
baz
qux
PATTERN2
ccc
ddd
我期待作为输出:
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
首选工具是AWK“单线程”。 Sed和其他解决方案也被接受了。如果包含解释会很好。
答案 0 :(得分:7)
这是使用asort()
对GNU awk中的数组进行排序的完美案例:
gawk '/PATTERN1/ {f=1; delete a}
/PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}
!f
f{a[$0]=$0}' file
这使用与How to select lines between two marker patterns which may occur multiple times with awk/sed类似的逻辑,并添加:
详细说明:
/PATTERN1/ {f=1; delete a}
找到匹配PATTERN1的行时,设置一个标志,并清除行数组。/PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]}
找到匹配PATTERN2的行时,将标志设置为关闭。另外,对包含范围内所有行的数组a[]
进行排序并打印它们。!f
如果标志关闭(即在范围之外),则评估为True,以便打印该行。f{a[$0]=$0}
如果该标志处于启用状态,请将该行存储在数组a[]
中,以便稍后可以使用该信息。▶ gawk '/PATTERN1/ {f=1} /PATTERN2/ {f=0; n=asort(a); for (i=1;i<=n;i++) print a[i]} !f; f{a[$0]=$0}' FILE
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
答案 1 :(得分:4)
您可以将sed
与head
和tail
:
{
sed '1,/^PATTERN1$/!d' FILE
sed '/^PATTERN1$/,/^PATTERN2$/!d' FILE | head -n-1 | tail -n+2 | sort
sed '/^PATTERN2$/,$!d' FILE
} > output
第一行打印从第1行到PATTERN1
的所有内容。
第二行取PATTERN1
和PATTERN2
之间的行,删除最后一行和第一行,并对剩余的行进行排序。
第三行打印从PATTERN2
到文件末尾的所有内容。
答案 2 :(得分:3)
更复杂,但可能会减轻存储大量行的内存负担(你的cfg文件必须非常庞大才能解决这个问题,但不过......)。使用GNU awk和排序协处理:
<head>
<link rel="stylesheet" href="{{ url_for('static', filename='fancybox/jquery.fancybox.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ url_for('static', filename='fancybox/helpers/jquery.fancybox-buttons.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ url_for('static', filename='fancybox/helpers/jquery.fancybox-thumbs.css') }}" type="text/css" media="screen" />
<!--<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>-->
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<!--<script type="text/javascript" src="{{ url_for('static', filename='js/lib/jquery-1.11.1.min.js') }}"></script>-->
<script type="text/javascript" src="{{ url_for('static', filename='js/lib/jquery.mousewheel-3.0.6.pack.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/lib/alertify.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/lib/jquery.slides.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='fancybox/jquery.fancybox.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='fancybox/helpers/jquery.fancybox-buttons.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='fancybox/helpers/jquery.fancybox-thumbs.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='fancybox/helpers/jquery.fancybox-media.js') }}"></script>
<script>
$(function() {
$(".signup-form").fancybox({
autoSize: false,
fitToView: false,
width: 813,
height : 603,
minWidth: 813,
minHeight : 603,
autoCenter: false,
autoScale: false,
autoDimensions: false,
type: "iframe"
// afterLoad: function () {
// this.width = $(this.element).data("width");
// this.height = $(this.element).data("height");
// }
});
}
</script>
</head>
<body>
...
<!-- trigger -->
<div class="sign-up"><a class="signup-form" data-fancybox-type="iframe" href="/signup" id="global-signup-link"><span>Sign up</span></a></div>
...
</body>
答案 3 :(得分:2)
有点不合常规,但是使用Vim:
vim -c 'exe "normal /PATTERN1\<cr>jV/PATTERN2\<cr>k: ! sort\<cr>" | wq!' FILE
\<cr>
是回车符,先输入 CTRL - v ,然后输入 CTRL - M 。
进一步的解释:
/PATTERN1\<cr>
-搜索第一个模式j
-转到下一行V
-进入视觉模式/PATTERN2\<cr>
-搜索第二个模式k
-返回上一行: ! sort\<cr>
-对您刚刚选择的可视文本进行排序wq!
-保存并退出答案 4 :(得分:1)
这是一个小巧且易于理解的shell脚本,用于对两种模式之间的行进行排序:
public float nightvalue = 0.4f;
public void Night()
{
// Change light intensity to nightvalue.
GL.GetComponent<Light2D>().intensity = nightvalue;
}
用法:<脚本路径> <输入文件> <输出文件>。
模式是硬编码在文件中的,可以根据需要进行更改(或用作参数)。此外,它还会创建一个临时文件来对中间数据进行排序(
算法:
从状态= 0开始并逐行读取文件。
在状态0下,将行写入输出文件,如果遇到START_PATTERN,则状态设置为1。
在状态1中,如果行不是STOP_PATTERN,则将行写入临时文件 在状态1中,如果line为STOP_PATTERN,则对临时文件进行排序,将临时文件的内容附加到输出文件(并删除临时文件),并将STOP_PATTERN写入输出文件。另外,将状态更改为0。
最后,如果临时文件中遗留了某些内容(缺少STOP_PATTERN的情况),请将临时文件的内容写入输出文件
答案 5 :(得分:0)
使用GNU sed(取决于Q
命令),由@choroba提出的解决方案:
{
sed -n '1,/PATTERN1/p' FILE
sed '1,/PATTERN1/d; /PATTERN2/Q' FILE | sort
sed -n '/PATTERN2/,$p' FILE
}
说明:
p
会在$
和'1,/PATTERN1/p'
中分别打印1到/ PATTERN1 /(含)和(/PATTERN2/,$p
是文件结尾)范围内的一行。 / li>
-n
会禁用打印所有行的默认行为。与p
结合使用。d
命令用于删除与/ PATTERN2匹配的第一行的/ PATTERN1 /的行1,以及Q
(不打印退出,仅GNU sed) /。这些是要排序的行,因此被送入sort
。答案 6 :(得分:0)
显然,这不如GNU AWK解决方案,但都是如此,这是GNU sed解决方案:
sed '
/PATTERN1/,/PATTERN2/ {
/PATTERN1/b # branch/break if /PATTERN1/. This line is printed
/PATTERN2/ { # if /PATTERN2/,
x # swap hold and pattern spaces
s/^\n// # delete the leading newline. The first H puts it there
s/.*/sort <<< "&"/e # sort the pattern space by calling Unix sort
p # print the sorted pattern space
x # swap hold and pattern space again to retrieve PATTERN2
p # print it also
}
H # Append the pattern space to the hold space
d # delete this line for now - it will be printed in the block above
}
' FILE
请注意,我依赖e
命令(GNU扩展)。
测试:
▶ gsed '
/PATTERN1/,/PATTERN2/ {
/PATTERN1/b
/PATTERN2/ {
x
s/^\n//; s/.*/sort <<< "&"/ep
x
p
}
H
d
}
' FILE
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd
答案 7 :(得分:0)
这也可以使用 non-GNU awk
和系统命令 sort
来完成,使其在 macOS 和 Linux 上都能运行。
awk -v SP='PATTERN1' -v EP='PATTERN2' -v cmd=sort '{
if (match($0, SP)>0) {flag=1}
else if (match($0, EP)>0) {
for (j=0;j<length(a);j++) {print a[j]|cmd}
close(cmd); delete a; i=0; flag=0}
else if (flag==1) {a[i++]=$0; next}
print $0
}' FILE
输出:
aaa
bbb
PATTERN1
bar
baz
foo
qux
PATTERN2
ccc
ddd